class ProxyCase( ModelThreadTestCase ): def setUp( self ): super( ProxyCase, self ).setUp() load_movie_fixtures() self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin( Person ) def _load_data( self, proxy = None ): """Trigger the loading of data by the proxy""" if proxy == None: proxy = self.proxy for row in range( proxy.rowCount() ): self._data( row, 0, proxy ) self.process() def _data( self, row, column, proxy = None ): """Get data from the proxy""" if proxy == None: proxy = self.proxy index = proxy.index( row, column ) return variant_to_pyobject( proxy.data( index ) ) def _set_data( self, row, column, value ): """Set data to the proxy""" index = self.proxy.index( row, column ) return self.proxy.setData( index, lambda:value )
class ProxyCase(ModelThreadTestCase): def setUp(self): super(ProxyCase, self).setUp() load_movie_fixtures() self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin(Person) def _load_data(self, proxy=None): """Trigger the loading of data by the proxy""" if proxy == None: proxy = self.proxy for row in range(proxy.rowCount()): self._data(row, 0, proxy) self.process() def _data(self, row, column, proxy=None): """Get data from the proxy""" if proxy == None: proxy = self.proxy index = proxy.index(row, column) return variant_to_pyobject(proxy.data(index)) def _set_data(self, row, column, value): """Set data to the proxy""" index = self.proxy.index(row, column) return self.proxy.setData(index, lambda: value)
class FormActionsCase( test_model.ExampleModelCase ): """Test the standard list actions. """ images_path = static_images_path def setUp( self ): super( FormActionsCase, self ).setUp() from camelot.model.party import Person from camelot.admin.application_admin import ApplicationAdmin self.query_proxy_case = test_proxy.QueryProxyCase('setUp') self.query_proxy_case.setUp() self.app_admin = ApplicationAdmin() self.model_context = MockModelContext() self.model_context.obj = Person.query.first() self.model_context.admin = self.app_admin.get_related_admin( Person ) self.gui_context = form_action.FormActionGuiContext() self.gui_context._model = self.query_proxy_case.proxy self.gui_context.widget_mapper = QtGui.QDataWidgetMapper() self.gui_context.widget_mapper.setModel( self.query_proxy_case.proxy ) self.gui_context.admin = self.app_admin.get_related_admin( Person ) def test_gui_context( self ): self.assertTrue( isinstance( self.gui_context.copy(), form_action.FormActionGuiContext ) ) self.assertTrue( isinstance( self.gui_context.create_model_context(), form_action.FormActionModelContext ) ) def test_previous_next( self ): previous_action = form_action.ToPreviousForm() previous_action.gui_run( self.gui_context ) next_action = form_action.ToNextForm() next_action.gui_run( self.gui_context ) first_action = form_action.ToFirstForm() first_action.gui_run( self.gui_context ) last_action = form_action.ToLastForm() last_action.gui_run( self.gui_context ) def test_show_history( self ): show_history_action = form_action.ShowHistory() list( show_history_action.model_run( self.model_context ) ) def test_close_form( self ): close_form_action = form_action.CloseForm() list( close_form_action.model_run( self.model_context ) )
class ModelCase( ModelThreadTestCase ): """Test the build in camelot model""" def setUp(self): super( ModelCase, self ).setUp() from camelot.model.party import Person from camelot.view.proxy.queryproxy import QueryTableProxy from camelot.admin.application_admin import ApplicationAdmin self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin( Person ) def test_person_contact_mechanism( self ): from camelot.model.party import Person person = Person( first_name = u'Robin', last_name = u'The brave' ) self.assertEqual( person.contact_mechanisms_email, None ) mechanism = ('email', '*****@*****.**') person.contact_mechanisms_email = mechanism self.person_admin.flush( person ) self.assertEqual( person.contact_mechanisms_email, mechanism ) self.person_admin.delete( person ) person = Person( first_name = u'Robin', last_name = u'The brave' ) self.person_admin.flush( person ) self.assertEqual( person.contact_mechanisms_email[1], u'' ) def test_fixture_version( self ): from camelot.model.party import Person from camelot.model.fixture import FixtureVersion FixtureVersion.set_current_version( 'demo_data', 0 ) self.assertEqual( FixtureVersion.get_current_version( 'demo_data' ), 0 ) example_file = os.path.join( os.path.dirname(__file__), '..', 'camelot_example', 'import_example.csv' ) person_count_before_import = Person.query.count() # begin load csv if fixture version import csv if FixtureVersion.get_current_version( 'demo_data' ) == 0: reader = csv.reader( open( example_file ) ) for line in reader: Person( first_name = line[0], last_name = line[1] ) FixtureVersion.set_current_version( 'demo_data', 1 ) Person.query.session.flush() # end load csv if fixture version self.assertTrue( Person.query.count() > person_count_before_import ) self.assertEqual( FixtureVersion.get_current_version( 'demo_data' ), 1 )
class QueryProxyCase( ModelThreadTestCase ): """Test the functionality of the QueryProxy to perform CRUD operations on stand alone data""" def setUp(self): super( QueryProxyCase, self ).setUp() from camelot_example.fixtures import load_movie_fixtures from camelot.model.party import Person from camelot.view.proxy.queryproxy import QueryTableProxy from camelot.admin.application_admin import ApplicationAdmin load_movie_fixtures() self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin( Person ) Person.query.count self.person_proxy = QueryTableProxy( self.person_admin, query_getter = lambda:Person.query, columns_getter = self.person_admin.get_columns ) def _load_data( self, proxy = None ): """Trigger the loading of data by the proxy""" if proxy == None: proxy = self.person_proxy for row in range( proxy.rowCount() ): self._data( row, 0, proxy ) self.process() def _data( self, row, column, proxy = None ): """Get data from the proxy""" if proxy == None: proxy = self.person_proxy index = proxy.index( row, column ) return variant_to_pyobject( proxy.data( index ) ) def _set_data( self, row, column, value ): """Set data to the proxy""" index = self.person_proxy.index( row, column ) return self.person_proxy.setData( index, lambda:value ) def test_insert_after_sort( self ): from camelot.view.proxy.queryproxy import QueryTableProxy from camelot.model.party import Person self.person_proxy.sort( 1, Qt.AscendingOrder ) # check the query self.assertTrue( self.person_proxy.columnCount() > 0 ) rowcount = self.person_proxy.rowCount() self.assertTrue( rowcount > 0 ) # check the sorting self._load_data() data0 = self._data( 0, 1 ) data1 = self._data( 1, 1 ) self.assertTrue( data1 > data0 ) self.person_proxy.sort( 1, Qt.DescendingOrder ) self._load_data() data0 = self._data( 0, 1 ) data1 = self._data( 1, 1 ) self.assertTrue( data0 > data1 ) # insert a new object person = Person() self.person_proxy.append_object( person ) new_rowcount = self.person_proxy.rowCount() self.assertTrue( new_rowcount > rowcount ) new_row = new_rowcount - 1 self.assertEqual( person, self.person_proxy._get_object( new_row ) ) # fill in the required fields self.assertFalse( self.person_admin.is_persistent( person ) ) self._set_data( new_row, 0, 'Foo' ) self._set_data( new_row, 1, 'Bar' ) self.assertEqual( person.first_name, 'Foo' ) self.assertEqual( person.last_name, 'Bar' ) self._load_data() self.assertEqual( self._data( new_row, 0 ), 'Foo' ) self.assertEqual( self._data( new_row, 1 ), 'Bar' ) self.assertTrue( self.person_admin.is_persistent( person ) ) # create a related proxy (eg, to display a form view) related_proxy = QueryTableProxy( self.person_admin, self.person_proxy.get_query_getter(), self.person_admin.get_columns, max_number_of_rows = 1, cache_collection_proxy = self.person_proxy ) self.assertEqual( new_rowcount, related_proxy.rowCount() ) self._load_data( related_proxy ) self.assertEqual( self._data( new_row, 0, related_proxy ), 'Foo' )
class ListActionsCase( ModelThreadTestCase ): """Test the standard list actions. """ images_path = static_images_path def setUp( self ): ModelThreadTestCase.setUp(self) from camelot_example.model import Movie from camelot.admin.application_admin import ApplicationAdmin self.app_admin = ApplicationAdmin() self.context = MockModelContext() self.context.obj = Movie.query.first() self.context.admin = self.app_admin.get_related_admin( Movie ) self.gui_context = GuiContext() self.gui_context.admin = self.app_admin.get_related_admin( Movie ) def test_sqlalchemy_command( self ): model_context = self.context from camelot.model.batch_job import BatchJobType # create a batch job to test with bt = BatchJobType( name = 'audit' ) model_context.session.add( bt ) bt.flush() # begin issue a query through the model_context model_context.session.query( BatchJobType ).update( values = {'name':'accounting audit'}, synchronize_session = 'evaluate' ) # end issue a query through the model_context # # the batch job should have changed self.assertEqual( bt.name, 'accounting audit' ) def test_change_row_actions( self ): from camelot.test.action import MockListActionGuiContext gui_context = MockListActionGuiContext() get_state = lambda action:action.get_state( gui_context.create_model_context() ) to_first = list_action.ToFirstRow() to_previous = list_action.ToPreviousRow() to_next = list_action.ToNextRow() to_last = list_action.ToLastRow() # the state does not change when the current row changes, # to make the actions usable in the main window toolbar to_last.gui_run( gui_context ) #self.assertFalse( get_state( to_last ).enabled ) #self.assertFalse( get_state( to_next ).enabled ) to_previous.gui_run( gui_context ) #self.assertTrue( get_state( to_last ).enabled ) #self.assertTrue( get_state( to_next ).enabled ) to_first.gui_run( gui_context ) #self.assertFalse( get_state( to_first ).enabled ) #self.assertFalse( get_state( to_previous ).enabled ) to_next.gui_run( gui_context ) #self.assertTrue( get_state( to_first ).enabled ) #self.assertTrue( get_state( to_previous ).enabled ) def test_print_preview( self ): print_preview = list_action.PrintPreview() for step in print_preview.model_run( self.context ): dialog = step.render( self.gui_context ) dialog.show() self.grab_widget( dialog ) def test_export_spreadsheet( self ): import xlrd export_spreadsheet = list_action.ExportSpreadsheet() for step in export_spreadsheet.model_run( self.context ): if isinstance( step, action_steps.OpenFile ): # see if the generated file can be parsed filename = step.get_path() xlrd.open_workbook( filename ) def test_match_names( self ): from camelot.view.import_utils import RowData, ColumnMapping rows = [ RowData( 0, ['rating', 'name'] ) ] mapping = ColumnMapping( 2, rows, self.context.admin ) self.assertNotEqual( mapping.column_0_field, 'rating' ) mapping.match_names() self.assertEqual( mapping.column_0_field, 'rating' ) def test_import_from_xls_file( self ): self.test_import_from_file( 'import_example.xls' ) def test_import_from_file( self, filename = 'import_example.csv' ): from camelot.model.party import Person example_folder = os.path.join( os.path.dirname(__file__), '..', 'camelot_example' ) self.context = MockModelContext() self.context.obj = Person.query.first() # need an object, to have a # session #self.assertTrue( self.context.obj != None ) self.context.admin = self.app_admin.get_related_admin( Person ) import_from_file = list_action.ImportFromFile() generator = import_from_file.model_run( self.context ) for step in generator: if isinstance( step, action_steps.SelectFile ): generator.send( [ os.path.join( example_folder, filename ) ] ) if isinstance( step, action_steps.ChangeObject ): dialog = step.render( self.gui_context ) dialog.show() self.grab_widget( dialog, suffix = 'column_selection' ) if isinstance( step, action_steps.ChangeObjects ): dialog = step.render() dialog.show() self.grab_widget( dialog, suffix = 'preview' ) if isinstance( step, action_steps.MessageBox ): dialog = step.render() dialog.show() self.grab_widget( dialog, suffix = 'confirmation' ) def test_replace_field_contents( self ): replace = list_action.ReplaceFieldContents() generator = replace.model_run( self.context ) for step in generator: if isinstance( step, action_steps.ChangeField ): dialog = step.render() dialog.show() self.grab_widget( dialog ) generator.send( ('rating', lambda:3) ) def test_drag_and_drop( self ): from camelot.view.proxy.queryproxy import QueryTableProxy class DropAction( Action ): pass mime_data = QtCore.QMimeData() admin = self.context.admin admin.drop_action = DropAction() proxy = QueryTableProxy( admin, admin.get_query, admin.get_columns ) proxy.dropMimeData( mime_data, Qt.MoveAction, -1, -1, QtCore.QModelIndex() )
class PartyCase(ModelThreadTestCase): """Test the build in party - address - contact mechanism model""" def setUp(self): super(PartyCase, self).setUp() from camelot.admin.application_admin import ApplicationAdmin self.session = Session() self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin(party.Person) self.organization_admin = self.app_admin.get_related_admin( party.Organization) def tearDown(self): self.session.expunge_all() def test_party(self): p = party.Party() self.assertFalse(p.name) def test_geographic_boundary(self): belgium = party.Country.get_or_create(code=u'BE', name=u'Belgium') self.assertTrue(unicode(belgium)) city = party.City.get_or_create(country=belgium, code='1000', name='Brussels') return city def test_address(self): city = self.test_geographic_boundary() address = party.Address.get_or_create(street1='Avenue Louise', street2=None, city=city) self.assertTrue(unicode(address)) return address def test_party_address(self): city = self.test_geographic_boundary() org = party.Organization(name='PSF') party_address = party.PartyAddress(party=org) party_address.street1 = 'Avenue Louise 5' party_address.street2 = 'Boite 4' party_address.city = city party_address_admin = party.AddressAdmin(self.app_admin, party.PartyAddress) self.assertTrue(party_address.address in party_address_admin. get_compounding_objects(party_address)) self.assertTrue(party_address.address in self.session.new) # everything should be flushed through the party admin org_admin = self.app_admin.get_related_admin(party.Organization) org_validator = org_admin.get_validator() self.assertTrue( party_address in org_admin.get_compounding_objects(org)) org_admin.flush(org) self.assertFalse(party_address.address in self.session.new) party_address_admin.refresh(party_address) # test hybrid property getters on Party and PartyAddress self.assertEqual(party_address.street1, 'Avenue Louise 5') self.assertEqual(party_address.street2, 'Boite 4') self.assertEqual(party_address.city, city) self.assertEqual(org.street1, 'Avenue Louise 5') self.assertEqual(org.street2, 'Boite 4') self.assertEqual(org.city, city) self.assertTrue(unicode(party_address)) query = self.session.query(party.PartyAddress) self.assertTrue( query.filter( party.PartyAddress.street1 == 'Avenue Louise 5').first()) self.assertTrue( query.filter(party.PartyAddress.street2 == 'Boite 4').first()) # if party address changes, party should be updated depending_objects = list( party_address_admin.get_depending_objects(party_address)) self.assertTrue(org in depending_objects) # if address changes, party address and party should be updated address = party_address.address address_admin = self.app_admin.get_related_admin(party.Address) depending_objects = list(address_admin.get_depending_objects(address)) self.assertTrue(party_address in depending_objects) self.assertTrue(org in depending_objects) # test hybrid property setters on Party org.street1 = 'Rue Belliard 1' org.street2 = 'Second floor' org.city = None # expunge should expunge the related address objects as well, so # after an expunge, the session as a whole can be flushed org_admin.expunge(org) self.session.flush() # test hybrid property setters on a new party org = party.Organization(name='PSF') org.street1 = 'Rue Belliard 1' org.street2 = 'Second floor' org.city = city org_admin.flush(org) self.assertEqual(len(org.addresses), 1) self.assertEqual(org.street1, 'Rue Belliard 1') self.assertEqual(org.street2, 'Second floor') self.assertEqual(org.city, city) # test invalidation of org object and refresh it self.assertFalse(org_validator.validate_object(org)) org.city = None self.assertTrue(org_validator.validate_object(org)) org_admin.refresh(org) self.assertFalse(org_validator.validate_object(org)) # removing all the address properties should make the # object valid again org.street1 = None org.street2 = None org.city = None self.assertFalse(org_validator.validate_object(org)) # removing all address properties of a not yet flushed # address should expunge the address org = party.Organization(name='PSF') org.street1 = 'Rue Belliard 1' for address in org.addresses: self.assertTrue(address in self.session.new) org.street1 = None self.assertTrue(address not in self.session) self.assertEqual(len(org.addresses), 0) def test_person(self): person = party.Person(first_name=u'Robin', last_name=u'The brave') self.assertEqual(person.email, None) self.assertEqual(person.phone, None) self.assertEqual(person.fax, None) self.assertEqual(person.street1, None) self.assertEqual(person.street2, None) self.assertEqual(person.city, None) self.person_admin.flush(person) person2 = party.Person(first_name=u'Robin') self.assertFalse(person2.note) person2.last_name = u'The brave' # gui should warn this person exists self.assertTrue(person2.note) return person def test_contact_mechanism(self): contact_mechanism = party.ContactMechanism(mechanism=(u'email', u'*****@*****.**')) self.assertTrue(unicode(contact_mechanism)) def test_person_contact_mechanism(self): # create a new person person = party.Person(first_name=u'Robin', last_name=u'The brave') self.person_admin.flush(person) self.assertEqual(person.email, None) # set the contact mechanism mechanism_1 = (u'email', u'*****@*****.**') person.email = mechanism_1 # the default from and thru dates should be set when # setting the party defaults self.person_admin.set_defaults(person) self.assertTrue(person.contact_mechanisms[0].from_date) self.person_admin.flush(person) self.assertEqual(person.email, mechanism_1) # change the contact mechanism, after a flush mechanism_2 = (u'email', u'*****@*****.**') person.email = mechanism_2 self.person_admin.flush(person) self.assertEqual(person.email, mechanism_2) # remove the contact mechanism after a flush person.email = ('email', '') self.assertEqual(person.email, None) self.person_admin.flush(person) self.assertEqual(person.email, None) admin = party.PartyContactMechanismAdmin(self.app_admin, party.PartyContactMechanism) contact_mechanism = party.ContactMechanism(mechanism=mechanism_1) party_contact_mechanism = party.PartyContactMechanism( party=person, contact_mechanism=contact_mechanism) admin.flush(party_contact_mechanism) admin.refresh(party_contact_mechanism) list(admin.get_depending_objects(party_contact_mechanism)) # # if the contact mechanism changes, the party person should be # updated as well # contact_mechanism_admin = self.app_admin.get_related_admin( party.ContactMechanism) depending_objects = list( contact_mechanism_admin.get_depending_objects(contact_mechanism)) self.assertTrue(person in depending_objects) self.assertTrue(party_contact_mechanism in depending_objects) # # if the party contact mechanism changes, the party should be updated # as well depending_objects = list( admin.get_depending_objects(party_contact_mechanism)) self.assertTrue(person in depending_objects) # delete the person self.person_admin.delete(person) def test_organization(self): org = party.Organization(name='PSF') org.email = ('email', '*****@*****.**') org.phone = ('phone', '1234') org.fax = ('fax', '4567') self.organization_admin.flush(org) self.assertTrue(unicode(org)) self.assertEqual(org.number_of_shares_issued, 0) query = orm.object_session(org).query(party.Organization) self.assertTrue( query.filter( party.Organization.email == ('email', '*****@*****.**')).first()) self.assertTrue( query.filter(party.Organization.phone == ('phone', '1234')).first()) self.assertTrue( query.filter(party.Organization.fax == ('fax', '4567')).first()) return org def test_party_relationship(self): person = self.test_person() org = self.test_organization() employee = party.EmployerEmployee(established_from=org, established_to=person) self.assertTrue(unicode(employee)) def test_party_contact_mechanism(self): person = self.test_person() party_contact_mechanism = party.PartyContactMechanism(party=person) party_contact_mechanism.mechanism = (u'email', u'*****@*****.**') party_contact_mechanism.mechanism = (u'email', u'*****@*****.**') self.assertTrue(party_contact_mechanism in self.session.new) self.assertTrue( party_contact_mechanism.contact_mechanism in self.session.new) # flushing trough the party should flush the contact mechanism self.person_admin.flush(person) self.assertFalse(party_contact_mechanism in self.session.new) self.assertFalse( party_contact_mechanism.contact_mechanism in self.session.new) self.assertTrue(unicode(party_contact_mechanism)) query = self.session.query(party.PartyContactMechanism) self.assertTrue( query.filter(party.PartyContactMechanism.mechanism == ( u'email', u'*****@*****.**')).first()) # party contact mechanism is only valid when contact mechanism is # valid party_contact_mechanism_admin = self.app_admin.get_related_admin( party.PartyContactMechanism) compounding_objects = list( party_contact_mechanism_admin.get_compounding_objects( party_contact_mechanism)) self.assertTrue( party_contact_mechanism.contact_mechanism in compounding_objects) party_contact_mechanism_validator = party_contact_mechanism_admin.get_validator( ) self.assertFalse( party_contact_mechanism_validator.validate_object( party_contact_mechanism)) party_contact_mechanism.contact_mechanism.mechanism = None self.assertTrue( party_contact_mechanism_validator.validate_object( party_contact_mechanism)) # the party is only valid when the contact mechanism is # valid party_admin = self.app_admin.get_related_admin(party.Person) party_validator = party_admin.get_validator() self.assertTrue(party_validator.validate_object(person)) def test_party_category(self): org = self.test_organization() category = party.PartyCategory(name=u'Imortant') category.parties.append(org) self.session.flush() self.assertTrue(list(category.get_contact_mechanisms(u'email'))) self.assertTrue(unicode(category))
class ApplicationActionsCase( test_model.ExampleModelCase ): """Test application actions. """ images_path = static_images_path def setUp(self): super( ApplicationActionsCase, self ).setUp() from camelot.admin.application_admin import ApplicationAdmin from camelot.core.files.storage import Storage from camelot.view.workspace import DesktopWorkspace self.app_admin = ApplicationAdmin() self.context = MockModelContext() self.storage = Storage() self.gui_context = application_action.ApplicationActionGuiContext() self.gui_context.admin = self.app_admin self.gui_context.workspace = DesktopWorkspace( self.app_admin, None ) def test_refresh( self ): from camelot.core.orm import Session from camelot.model.party import Person refresh_action = application_action.Refresh() session = Session() session.expunge_all() # create objects in various states # p1 = Person(first_name = u'p1', last_name = u'persistent' ) p2 = Person(first_name = u'p2', last_name = u'dirty' ) p3 = Person(first_name = u'p3', last_name = u'deleted' ) p4 = Person(first_name = u'p4', last_name = u'to be deleted' ) p5 = Person(first_name = u'p5', last_name = u'detached' ) p6 = Person(first_name = u'p6', last_name = u'deleted outside session' ) session.flush() p3.delete() session.flush() p4.delete() p2.last_name = u'clean' # # delete p6 without the session being aware # person_table = Person.table session.execute( person_table.delete().where( person_table.c.party_id == p6.id ) ) # # refresh the session through the action # list( refresh_action.model_run( self.context ) ) self.assertEqual( p2.last_name, u'dirty' ) def test_backup_and_restore( self ): backup_action = application_action.Backup() generator = backup_action.model_run( self.context ) for step in generator: if isinstance( step, action_steps.SelectBackup ): dialog = step.render() dialog.show() self.grab_widget( dialog, suffix = 'backup' ) generator.send( ('unittest', self.storage) ) restore_action = application_action.Restore() generator = restore_action.model_run( self.context ) for step in generator: if isinstance( step, action_steps.SelectRestore ): dialog = step.render() dialog.show() self.grab_widget( dialog, suffix = 'restore' ) generator.send( ('unittest', self.storage) ) def test_show_help( self ): show_help_action = application_action.ShowHelp() show_help_action.gui_run( self.gui_context ) def test_change_logging( self ): change_logging_action = application_action.ChangeLogging() change_logging_action.model_run( self.context ) def test_open_table_view( self ): from camelot.model.party import Person person_admin = self.app_admin.get_related_admin( Person ) open_table_view_action = application_action.OpenTableView( person_admin ) open_table_view_action.gui_run( self.gui_context ) def test_open_new_view( self ): from camelot.model.party import Person person_admin = self.app_admin.get_related_admin( Person ) open_new_view_action = application_action.OpenNewView( person_admin ) open_new_view_action.gui_run( self.gui_context ) def test_change_logging( self ): change_logging_action = application_action.ChangeLogging() for step in change_logging_action.model_run( self.context ): if isinstance( step, action_steps.ChangeObject ): step.get_object().level = logging.INFO def test_dump_state( self ): dump_state = application_action.DumpState() list( dump_state.model_run( self.context ) ) def test_runtime_info( self ): runtime_info = application_action.RuntimeInfo() list( runtime_info.model_run( self.context ) ) def test_segmentation_fault( self ): segmentation_fault = application_action.SegmentationFault() list( segmentation_fault.model_run( self.context ) )
class ListActionsCase( test_model.ExampleModelCase ): """Test the standard list actions. """ images_path = static_images_path def setUp( self ): super( ListActionsCase, self ).setUp() from camelot_example.model import Movie from camelot.admin.application_admin import ApplicationAdmin self.query_proxy_case = test_proxy.QueryProxyCase('setUp') self.query_proxy_case.setUp() self.app_admin = ApplicationAdmin() self.context = MockModelContext() self.context.obj = Movie.query.first() self.context.admin = self.app_admin.get_related_admin( Movie ) self.gui_context = list_action.ListActionGuiContext() self.gui_context.admin = self.app_admin.get_related_admin( Movie ) table_widget = tableview.AdminTableWidget( self.gui_context.admin ) table_widget.setModel( self.query_proxy_case.proxy ) self.gui_context.item_view = table_widget def tearDown( self ): Session().expunge_all() def test_gui_context( self ): self.assertTrue( isinstance( self.gui_context.copy(), list_action.ListActionGuiContext ) ) model_context = self.gui_context.create_model_context() self.assertTrue( isinstance( model_context, list_action.ListActionModelContext ) ) list( model_context.get_collection() ) list( model_context.get_selection() ) model_context.get_object() def test_sqlalchemy_command( self ): model_context = self.context from camelot.model.batch_job import BatchJobType # create a batch job to test with bt = BatchJobType( name = 'audit' ) model_context.session.add( bt ) bt.flush() # begin issue a query through the model_context model_context.session.query( BatchJobType ).update( values = {'name':'accounting audit'}, synchronize_session = 'evaluate' ) # end issue a query through the model_context # # the batch job should have changed self.assertEqual( bt.name, 'accounting audit' ) def test_change_row_actions( self ): from camelot.test.action import MockListActionGuiContext gui_context = MockListActionGuiContext() get_state = lambda action:action.get_state( gui_context.create_model_context() ) to_first = list_action.ToFirstRow() to_previous = list_action.ToPreviousRow() to_next = list_action.ToNextRow() to_last = list_action.ToLastRow() # the state does not change when the current row changes, # to make the actions usable in the main window toolbar to_last.gui_run( gui_context ) #self.assertFalse( get_state( to_last ).enabled ) #self.assertFalse( get_state( to_next ).enabled ) to_previous.gui_run( gui_context ) #self.assertTrue( get_state( to_last ).enabled ) #self.assertTrue( get_state( to_next ).enabled ) to_first.gui_run( gui_context ) #self.assertFalse( get_state( to_first ).enabled ) #self.assertFalse( get_state( to_previous ).enabled ) to_next.gui_run( gui_context ) #self.assertTrue( get_state( to_first ).enabled ) #self.assertTrue( get_state( to_previous ).enabled ) def test_print_preview( self ): print_preview = list_action.PrintPreview() for step in print_preview.model_run( self.context ): dialog = step.render( self.gui_context ) dialog.show() self.grab_widget( dialog ) def test_export_spreadsheet( self ): import xlrd export_spreadsheet = list_action.ExportSpreadsheet() for step in export_spreadsheet.model_run( self.context ): if isinstance( step, action_steps.OpenFile ): # see if the generated file can be parsed filename = step.get_path() xlrd.open_workbook( filename ) def test_match_names( self ): from camelot.view.import_utils import RowData, ColumnMapping rows = [ RowData( 0, ['rating', 'name'] ) ] fields = [field for field, _fa in self.context.admin.get_columns()] mapping = ColumnMapping( 2, rows, self.context.admin, fields ) self.assertNotEqual( mapping.column_0_field, 'rating' ) mapping.match_names() self.assertEqual( mapping.column_0_field, 'rating' ) def test_import_from_xls_file( self ): self.test_import_from_file( 'import_example.xls' ) def test_import_from_file( self, filename = 'import_example.csv' ): from camelot.model.party import Person example_folder = os.path.join( os.path.dirname(__file__), '..', 'camelot_example' ) self.context = MockModelContext() self.context.obj = Person.query.first() # need an object, to have a # session #self.assertTrue( self.context.obj != None ) self.context.admin = self.app_admin.get_related_admin( Person ) import_from_file = list_action.ImportFromFile() generator = import_from_file.model_run( self.context ) for step in generator: if isinstance( step, action_steps.SelectFile ): generator.send( [ os.path.join( example_folder, filename ) ] ) if isinstance( step, action_steps.ChangeObject ): dialog = step.render( self.gui_context ) dialog.show() self.grab_widget( dialog, suffix = 'column_selection' ) if isinstance( step, action_steps.ChangeObjects ): dialog = step.render() dialog.show() self.grab_widget( dialog, suffix = 'preview' ) if isinstance( step, action_steps.MessageBox ): dialog = step.render() dialog.show() self.grab_widget( dialog, suffix = 'confirmation' ) def test_replace_field_contents( self ): replace = list_action.ReplaceFieldContents() generator = replace.model_run( self.context ) for step in generator: if isinstance( step, action_steps.ChangeField ): dialog = step.render() dialog.show() self.grab_widget( dialog ) generator.send( ('rating', lambda:3) ) def test_drag_and_drop( self ): from camelot.view.proxy.queryproxy import QueryTableProxy class DropAction( Action ): pass mime_data = QtCore.QMimeData() admin = self.context.admin admin.drop_action = DropAction() proxy = QueryTableProxy( admin, admin.get_query, admin.get_columns ) proxy.dropMimeData( mime_data, Qt.MoveAction, -1, -1, QtCore.QModelIndex() ) def test_open_form_view( self ): open_form_view_action = list_action.OpenFormView() open_form_view_action.gui_run( self.gui_context ) def test_open_new_view( self ): open_new_view_action = list_action.OpenNewView() open_new_view_action.gui_run( self.gui_context ) def test_duplicate_selection( self ): query = self.context.admin.entity.query pre_duplication = query.count() duplicate_selection_action = list_action.DuplicateSelection() duplicate_selection_action.model_run( self.context ) post_duplication = query.count() #self.assertEqual( pre_duplication + 1, post_duplication ) def test_delete_selection( self ): session = orm.object_session( self.context.obj ) self.assertTrue( self.context.obj in session ) delete_selection_action = list_action.DeleteSelection() delete_selection_action.gui_run( self.gui_context ) list( delete_selection_action.model_run( self.context ) ) self.assertFalse( self.context.obj in session ) def test_add_existing_object( self ): add_existing_object_action = list_action.AddExistingObject() list( add_existing_object_action.model_run( self.context ) ) def test_add_new_object( self ): add_new_object_action = list_action.AddNewObject() add_new_object_action.gui_run( self.gui_context ) def test_remove_selection( self ): remove_selection_action = list_action.RemoveSelection() list( remove_selection_action.model_run( self.gui_context.create_model_context() ) ) def test_call_method( self ): call_method_action = list_action.CallMethod( 'Call', lambda x:True ) list( call_method_action.model_run( self.context ) )
class ModelCase(ModelThreadTestCase): """Test the build in camelot model""" def setUp(self): super(ModelCase, self).setUp() from camelot.model.party import Person from camelot.view.proxy.queryproxy import QueryTableProxy from camelot.admin.application_admin import ApplicationAdmin self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin(Person) def test_batch_job(self): from camelot.model.batch_job import BatchJob, BatchJobType batch_job_type = BatchJobType.get_or_create(u"Synchronize") with BatchJob.create(batch_job_type) as batch_job: batch_job.add_strings_to_message([u"Doing something"]) batch_job.add_strings_to_message([u"Done"], color="green") def test_current_authentication(self): from camelot.model.authentication import get_current_authentication authentication = get_current_authentication() # current authentication cache should survive # a session expire + expunge orm.object_session(authentication).expire_all() orm.object_session(authentication).expunge_all() authentication = get_current_authentication() self.assertTrue(authentication.username) def test_person_contact_mechanism(self): from camelot.model.party import Person mechanism_1 = (u"email", u"*****@*****.**") mechanism_2 = (u"email", u"*****@*****.**") person = Person(first_name=u"Robin", last_name=u"The brave") self.assertEqual(person.email, None) person.email = mechanism_1 self.person_admin.flush(person) self.assertEqual(person.email, mechanism_1) person.email = mechanism_2 self.assertEqual(person.email, mechanism_2) self.person_admin.delete(person) person = Person(first_name=u"Robin", last_name=u"The brave") self.person_admin.flush(person) self.assertEqual(person.email, None) person.email = mechanism_2 person.email = None self.assertEqual(person.email, None) self.person_admin.flush(person) self.assertEqual(person.email, None) def test_fixture_version(self): from camelot.model.party import Person from camelot.model.fixture import FixtureVersion FixtureVersion.set_current_version(u"demo_data", 0) self.assertEqual(FixtureVersion.get_current_version(u"demo_data"), 0) example_file = os.path.join(os.path.dirname(__file__), "..", "camelot_example", "import_example.csv") person_count_before_import = Person.query.count() # begin load csv if fixture version import csv if FixtureVersion.get_current_version(u"demo_data") == 0: reader = csv.reader(open(example_file)) for line in reader: Person(first_name=line[0], last_name=line[1]) FixtureVersion.set_current_version(u"demo_data", 1) Person.query.session.flush() # end load csv if fixture version self.assertTrue(Person.query.count() > person_count_before_import) self.assertEqual(FixtureVersion.get_current_version(u"demo_data"), 1)
class PartyCase( ModelThreadTestCase ): """Test the build in party - address - contact mechanism model""" def setUp(self): super( PartyCase, self ).setUp() from camelot.admin.application_admin import ApplicationAdmin self.session = Session() self.app_admin = ApplicationAdmin() self.person_admin = self.app_admin.get_related_admin( party.Person ) self.organization_admin = self.app_admin.get_related_admin( party.Organization ) def tearDown(self): self.session.expunge_all() def test_party( self ): p = party.Party() self.assertFalse( p.name ) def test_geographic_boundary( self ): belgium = party.Country.get_or_create( code = u'BE', name = u'Belgium' ) self.assertTrue( unicode( belgium ) ) city = party.City.get_or_create( country = belgium, code = '1000', name = 'Brussels' ) return city def test_address( self ): city = self.test_geographic_boundary() address = party.Address.get_or_create( street1 = 'Avenue Louise', street2 = None, city = city ) self.assertTrue( unicode( address ) ) return address def test_party_address( self ): city = self.test_geographic_boundary() org = party.Organization( name = 'PSF' ) party_address = party.PartyAddress( party = org ) party_address.street1 = 'Avenue Louise 5' party_address.street2 = 'Boite 4' party_address.city = city party_address_admin = party.AddressAdmin( self.app_admin, party.PartyAddress ) self.assertTrue( party_address.address in party_address_admin.get_compounding_objects( party_address ) ) self.assertTrue( party_address.address in self.session.new ) # everything should be flushed through the party admin org_admin = self.app_admin.get_related_admin( party.Organization ) org_validator = org_admin.get_validator() self.assertTrue( party_address in org_admin.get_compounding_objects( org ) ) org_admin.flush( org ) self.assertFalse( party_address.address in self.session.new ) party_address_admin.refresh( party_address ) # test hybrid property getters on Party and PartyAddress self.assertEqual( party_address.street1, 'Avenue Louise 5' ) self.assertEqual( party_address.street2, 'Boite 4' ) self.assertEqual( party_address.city, city ) self.assertEqual( org.street1, 'Avenue Louise 5' ) self.assertEqual( org.street2, 'Boite 4' ) self.assertEqual( org.city, city ) self.assertTrue( unicode( party_address ) ) query = self.session.query( party.PartyAddress ) self.assertTrue( query.filter( party.PartyAddress.street1 == 'Avenue Louise 5' ).first() ) self.assertTrue( query.filter( party.PartyAddress.street2 == 'Boite 4' ).first() ) # if party address changes, party should be updated depending_objects = list( party_address_admin.get_depending_objects( party_address ) ) self.assertTrue( org in depending_objects ) # if address changes, party address and party should be updated address = party_address.address address_admin = self.app_admin.get_related_admin( party.Address ) depending_objects = list( address_admin.get_depending_objects( address ) ) self.assertTrue( party_address in depending_objects ) self.assertTrue( org in depending_objects ) # test hybrid property setters on Party org.street1 = 'Rue Belliard 1' org.street2 = 'Second floor' org.city = None # expunge should expunge the related address objects as well, so # after an expunge, the session as a whole can be flushed org_admin.expunge( org ) self.session.flush() # test hybrid property setters on a new party org = party.Organization( name = 'PSF' ) org.street1 = 'Rue Belliard 1' org.street2 = 'Second floor' org.city = city org_admin.flush( org ) self.assertEqual( len( org.addresses ), 1 ) self.assertEqual( org.street1, 'Rue Belliard 1' ) self.assertEqual( org.street2, 'Second floor' ) self.assertEqual( org.city, city ) # test invalidation of org object and refresh it self.assertFalse( org_validator.validate_object( org ) ) org.city = None self.assertTrue( org_validator.validate_object( org ) ) org_admin.refresh( org ) self.assertFalse( org_validator.validate_object( org ) ) # removing all the address properties should make the # object valid again org.street1 = None org.street2 = None org.city = None self.assertFalse( org_validator.validate_object( org ) ) # removing all address properties of a not yet flushed # address should expunge the address org = party.Organization( name = 'PSF' ) org.street1 = 'Rue Belliard 1' for address in org.addresses: self.assertTrue( address in self.session.new ) org.street1 = None self.assertTrue( address not in self.session ) self.assertEqual( len(org.addresses), 0 ) def test_person( self ): person = party.Person( first_name = u'Robin', last_name = u'The brave' ) self.assertEqual( person.email, None ) self.assertEqual( person.phone, None ) self.assertEqual( person.fax, None ) self.assertEqual( person.street1, None ) self.assertEqual( person.street2, None ) self.assertEqual( person.city, None ) self.person_admin.flush( person ) person2 = party.Person( first_name = u'Robin' ) self.assertFalse( person2.note ) person2.last_name = u'The brave' # gui should warn this person exists self.assertTrue( person2.note ) return person def test_contact_mechanism( self ): contact_mechanism = party.ContactMechanism( mechanism = (u'email', u'*****@*****.**') ) self.assertTrue( unicode( contact_mechanism ) ) def test_person_contact_mechanism( self ): # create a new person person = party.Person( first_name = u'Robin', last_name = u'The brave' ) self.person_admin.flush( person ) self.assertEqual( person.email, None ) # set the contact mechanism mechanism_1 = (u'email', u'*****@*****.**') person.email = mechanism_1 # the default from and thru dates should be set when # setting the party defaults self.person_admin.set_defaults( person ) self.assertTrue( person.contact_mechanisms[0].from_date ) self.person_admin.flush( person ) self.assertEqual( person.email, mechanism_1 ) # change the contact mechanism, after a flush mechanism_2 = (u'email', u'*****@*****.**') person.email = mechanism_2 self.person_admin.flush( person ) self.assertEqual( person.email, mechanism_2 ) # remove the contact mechanism after a flush person.email = ('email', '') self.assertEqual( person.email, None ) self.person_admin.flush( person ) self.assertEqual( person.email, None ) admin = party.PartyContactMechanismAdmin( self.app_admin, party.PartyContactMechanism ) contact_mechanism = party.ContactMechanism( mechanism = mechanism_1 ) party_contact_mechanism = party.PartyContactMechanism( party = person, contact_mechanism = contact_mechanism ) admin.flush( party_contact_mechanism ) admin.refresh( party_contact_mechanism ) list( admin.get_depending_objects( party_contact_mechanism ) ) # # if the contact mechanism changes, the party person should be # updated as well # contact_mechanism_admin = self.app_admin.get_related_admin( party.ContactMechanism ) depending_objects = list( contact_mechanism_admin.get_depending_objects( contact_mechanism ) ) self.assertTrue( person in depending_objects ) self.assertTrue( party_contact_mechanism in depending_objects ) # # if the party contact mechanism changes, the party should be updated # as well depending_objects = list( admin.get_depending_objects( party_contact_mechanism ) ) self.assertTrue( person in depending_objects ) # delete the person self.person_admin.delete( person ) def test_organization( self ): org = party.Organization( name = 'PSF' ) org.email = ('email', '*****@*****.**') org.phone = ('phone', '1234') org.fax = ('fax', '4567') self.organization_admin.flush( org ) self.assertTrue( unicode( org ) ) self.assertEqual( org.number_of_shares_issued, 0 ) query = orm.object_session( org ).query( party.Organization ) self.assertTrue( query.filter( party.Organization.email == ('email', '*****@*****.**') ).first() ) self.assertTrue( query.filter( party.Organization.phone == ('phone', '1234') ).first() ) self.assertTrue( query.filter( party.Organization.fax == ('fax', '4567') ).first() ) return org def test_party_relationship( self ): person = self.test_person() org = self.test_organization() employee = party.EmployerEmployee( established_from = org, established_to = person ) self.assertTrue( unicode( employee ) ) def test_party_contact_mechanism( self ): person = self.test_person() party_contact_mechanism = party.PartyContactMechanism( party = person ) party_contact_mechanism.mechanism = (u'email', u'*****@*****.**') party_contact_mechanism.mechanism = (u'email', u'*****@*****.**') self.assertTrue( party_contact_mechanism in self.session.new ) self.assertTrue( party_contact_mechanism.contact_mechanism in self.session.new ) # flushing trough the party should flush the contact mechanism self.person_admin.flush( person ) self.assertFalse( party_contact_mechanism in self.session.new ) self.assertFalse( party_contact_mechanism.contact_mechanism in self.session.new ) self.assertTrue( unicode( party_contact_mechanism ) ) query = self.session.query( party.PartyContactMechanism ) self.assertTrue( query.filter( party.PartyContactMechanism.mechanism == (u'email', u'*****@*****.**') ).first() ) # party contact mechanism is only valid when contact mechanism is # valid party_contact_mechanism_admin = self.app_admin.get_related_admin( party.PartyContactMechanism ) compounding_objects = list( party_contact_mechanism_admin.get_compounding_objects( party_contact_mechanism ) ) self.assertTrue( party_contact_mechanism.contact_mechanism in compounding_objects ) party_contact_mechanism_validator = party_contact_mechanism_admin.get_validator() self.assertFalse( party_contact_mechanism_validator.validate_object( party_contact_mechanism ) ) party_contact_mechanism.contact_mechanism.mechanism = None self.assertTrue( party_contact_mechanism_validator.validate_object( party_contact_mechanism ) ) # the party is only valid when the contact mechanism is # valid party_admin = self.app_admin.get_related_admin( party.Person ) party_validator = party_admin.get_validator() self.assertTrue( party_validator.validate_object( person ) ) def test_party_category( self ): org = self.test_organization() category = party.PartyCategory( name = u'Imortant' ) category.parties.append( org ) self.session.flush() self.assertTrue( list( category.get_contact_mechanisms( u'email') ) ) self.assertTrue( unicode( category ) )
class ObjectAdminCase(ModelThreadTestCase): """Test the ObjectAdmin """ def setUp(self): super(ObjectAdminCase, self).setUp() self.app_admin = ApplicationAdmin() def test_not_editable_admin_class_decorator(self): from camelot.model.i18n import Translation from camelot.admin.not_editable_admin import not_editable_admin OriginalAdmin = Translation.Admin original_admin = OriginalAdmin(self.app_admin, Translation) self.assertTrue(len(original_admin.get_list_actions())) self.assertTrue( original_admin.get_field_attributes('value')['editable']) # # enable the actions # NewAdmin = not_editable_admin(Translation.Admin, actions=True) new_admin = NewAdmin(self.app_admin, Translation) self.assertTrue(len(new_admin.get_list_actions())) self.assertFalse(new_admin.get_field_attributes('value')['editable']) self.assertFalse(new_admin.get_field_attributes('source')['editable']) # # disable the actions # NewAdmin = not_editable_admin(Translation.Admin, actions=False) new_admin = NewAdmin(self.app_admin, Translation) self.assertFalse(len(new_admin.get_list_actions())) self.assertFalse(new_admin.get_field_attributes('value')['editable']) self.assertFalse(new_admin.get_field_attributes('source')['editable']) # # keep the value field editalbe # NewAdmin = not_editable_admin(Translation.Admin, editable_fields=['value']) new_admin = NewAdmin(self.app_admin, Translation) self.assertFalse(len(new_admin.get_list_actions())) self.assertTrue(new_admin.get_field_attributes('value')['editable']) self.assertFalse(new_admin.get_field_attributes('source')['editable']) def test_signature(self): # # Test a group of methods, required for an ObjectAdmin # class A(object): def __init__(self): self.x = 1 self.y = 2 class Admin(ObjectAdmin): list_display = ['x', 'y'] a = A() a_admin = self.app_admin.get_related_admin(A) self.assertTrue(str(a_admin)) self.assertTrue(repr(a_admin)) self.assertFalse(a_admin.primary_key(a)) self.assertTrue(isinstance(a_admin.get_modifications(a), dict)) a_admin.get_icon() a_admin.flush(a) a_admin.delete(a) a_admin.expunge(a) a_admin.refresh(a) a_admin.add(a) a_admin.is_deleted(a) a_admin.is_persistent(a) a_admin.copy(a)