def test_cutting_editor(self):
     loc = Location(name=u'name', code=u'code')
     plant = Plant(accession=self.accession, location=loc, code=u'1',
                   quantity=1)
     propagation = Propagation()
     plant.propagations.append(propagation)
     self.editor = PropagationEditor(model=propagation)
     widgets = self.editor.presenter.view.widgets
     view = self.editor.presenter.view
     view.set_widget_value('prop_type_combo', u'UnrootedCutting')
     view.set_widget_value('prop_date_entry', utils.today_str())
     cutting_presenter = self.editor.presenter._cutting_presenter
     for widget, attr in cutting_presenter.widget_to_field_map.iteritems():
         #debug('%s=%s' % (widget, default_cutting_values[attr]))
         view.set_widget_value(widget, default_cutting_values[attr])
     update_gui()
     self.editor.handle_response(gtk.RESPONSE_OK)
     self.editor.commit_changes()
     model = self.editor.model
     s = object_session(model)
     s.expire(model)
     self.assert_(model.prop_type == u'UnrootedCutting')
     for attr, value in default_cutting_values.iteritems():
         v = getattr(model._cutting, attr)
         self.assert_(v==value, '%s = %s(%s)' % (attr, value, v))
     self.editor.session.close()
    def test_accession_editor(self):
        acc = Accession(code=u'code', species=self.species)
        self.editor = AccessionEditor(acc)
        update_gui()

        widgets = self.editor.presenter.view.widgets
        # make sure there is a problem if the species entry text isn't
        # a species string
        widgets.acc_species_entry.set_text('asdasd')
        assert self.editor.presenter.problems

        # make sure the problem is removed if the species entry text
        # is set to a species string

        # fill in the completions
        widgets.acc_species_entry.set_text(str(self.species)[0:3])
        update_gui() # ensures idle callback is called to add completions
        # set the fill string which should match from completions
        widgets.acc_species_entry.set_text(str(self.species))
        assert not self.editor.presenter.problems,self.editor.presenter.problems

        # commit the changes and cleanup
        self.editor.model.name = u'asda'
        import gtk
        self.editor.handle_response(gtk.RESPONSE_OK)
        self.editor.session.close()
    def test_seed_editor_load(self):
        loc = Location(name=u'name', code=u'code')
        plant = Plant(accession=self.accession, location=loc, code=u'1',
                      quantity=1)
        propagation = Propagation(**default_propagation_values)
        propagation.prop_type = u'Seed'
        propagation._seed = PropSeed(**default_seed_values)
        plant.propagations.append(propagation)

        editor = PropagationEditor(model=propagation)
        widgets = editor.presenter.view.widgets
        seed_presenter = editor.presenter._seed_presenter
        view = editor.presenter.view

        update_gui()

        # check that the values loaded correctly from the model in the
        # editor widget
        def get_widget_text(w):
            if isinstance(w, gtk.TextView):
                return w.get_buffer().props.text
            elif isinstance(w, gtk.Entry):
                return w.props.text
            elif isinstance(w, gtk.ComboBoxEntry):
                return w.get_active_text()
            else:
                raise ValueError('%s not supported' % type(w))

        # make sure the default values match the values in the widgets
        date_format = prefs.prefs[prefs.date_format_pref]
        for widget, attr in editor.presenter.widget_to_field_map.iteritems():
            if not attr in default_propagation_values:
                continue
            default = default_propagation_values[attr]
            if isinstance(default, datetime.date):
                default = default.strftime(date_format)
            value = get_widget_text(widgets[widget])
            self.assert_(value == default,
                         '%s = %s (%s)' % (attr, value, default))

        # check the default for the PropSeed and SeedPresenter
        for widget, attr in seed_presenter.widget_to_field_map.iteritems():
            if not attr in default_seed_values:
                continue
            default = default_seed_values[attr]
            if isinstance(default, datetime.date):
                default = default.strftime(date_format)
            if isinstance(default, int):
                default = str(default)
            value = get_widget_text(widgets[widget])
            self.assert_(value == default,
                         '%s = %s (%s)' % (attr, value, default))
    def test_accession_source_editor(self, accession=None):
        acc = self.create(Accession, species=self.species, code=u'parent')
        plant = self.create(Plant, accession=acc, quantity=1,
                            location=Location(name=u'site', code=u'STE'),
                            code=u'1')
        # creating a dummy propagtion without a related seed/cutting
        prop = self.create(Propagation, prop_type='Seed')
        plant.propagations.append(prop)
        self.session.commit()
        plant_prop_id = prop.id
        assert plant_prop_id # assert we got a valid id after the commit

        acc = Accession(code=u'code', species=self.species)
        self.editor = AccessionEditor(acc)
        # normally called by editor.presenter.start() but we don't call it here
        self.editor.presenter.source_presenter.start()
        widgets = self.editor.presenter.view.widgets
        update_gui()

        # set the date so the presenter will be "dirty"
        widgets.acc_date_recvd_entry.props.text = utils.today_str()

        # set the source type as "Garden Propagation"
        widgets.acc_source_comboentry.child.props.text = \
            SourcePresenter.garden_prop_str
        assert not self.editor.presenter.problems

        # set the source plant
        widgets.source_prop_plant_entry.props.text = str(plant)
        update_gui()
        comp = widgets.source_prop_plant_entry.get_completion()
        comp.emit('match-selected', comp.get_model(),
                  comp.get_model().get_iter_first())

        # assert that the propagations were added to the treevide
        treeview = widgets.source_prop_treeview
        assert treeview.get_model()

        # select the first/only propagation in the treeview
        toggle_cell = widgets.prop_toggle_cell.emit('toggled', 0)

        # commit the changes and cleanup
        import gtk
        self.editor.handle_response(gtk.RESPONSE_OK)
        self.editor.session.close()

        # open a seperate session and make sure everything committed
        session = db.Session()
        acc = session.query(Accession).filter_by(code=u'code')[0]
        parent = session.query(Accession).filter_by(code=u'parent')[0]
        assert acc.source.plant_propagation_id == plant_prop_id
    def test_seed_editor_commit(self):
        loc = Location(name=u'name', code=u'code')
        plant = Plant(accession=self.accession, location=loc, code=u'1',
                      quantity=1)
        propagation = Propagation()
        plant.propagations.append(propagation)
        editor = PropagationEditor(model=propagation)
        widgets = editor.presenter.view.widgets
        seed_presenter = editor.presenter._seed_presenter
        view = editor.presenter.view

        # set default values in editor widgets
        view.set_widget_value('prop_type_combo', u'Seed')
        view.set_widget_value('prop_date_entry',
                              default_propagation_values['date'])
        view.set_widget_value('notes_textview',
                              default_propagation_values['notes'])
        for widget, attr in seed_presenter.widget_to_field_map.iteritems():
            w = widgets[widget]
            if isinstance(w, gtk.ComboBoxEntry) and not w.get_model():
                widgets[widget].child.props.text = default_seed_values[attr]
            view.set_widget_value(widget, default_seed_values[attr])

        # update the editor, send the RESPONSE_OK signal and commit the changes
        update_gui()
        editor.handle_response(gtk.RESPONSE_OK)
        editor.presenter.cleanup()
        model_id = editor.model.id
        editor.commit_changes()
        editor.session.close()

        s = db.Session()
        propagation = s.query(Propagation).get(model_id)

        self.assert_(propagation.prop_type == u'Seed')
        # make sure the each value in default_seed_values matches the model
        for attr, expected in default_seed_values.iteritems():
            v = getattr(propagation._seed, attr)
            if isinstance(v, datetime.date):
                format = prefs.prefs[prefs.date_format_pref]
                v = v.strftime(format)
                if isinstance(expected, datetime.date):
                    expected = expected.strftime(format)
            self.assert_(v==expected, '%s = %s(%s)' % (attr, expected, v))

        for attr, expected in default_propagation_values.iteritems():
            v = getattr(propagation, attr)
            self.assert_(v==expected, '%s = %s(%s)' % (attr, expected, v))

        s.close()
    def test_branch_editor(self):
        try:
            import gtk
        except ImportError:
            raise SkipTest('could not import gtk')

        # test argument checks
        #
        # TODO: these argument checks make future tests fail because
        # the PlantEditor is never cleaned up
        #
        # self.assert_(PlantEditor())
        # self.assertRaises(CheckConditionError, PlantEditor, branch_mode=True)

        # plant = Plant(accession=self.accession, location=self.location,
        #               code=u'33', quantity=5)
        # self.assertRaises(CheckConditionError, PlantEditor, model=plant,
        #                   branch_mode=True)
        #self.accession.plants.remove(plant) # remove from session
        # TODO: test check where quantity < 2

        quantity = 5
        self.plant.quantity = quantity
        self.session.commit()
        self.editor = PlantEditor(model=self.plant, branch_mode=True)
        update_gui()

        widgets = self.editor.presenter.view.widgets
        new_quantity = 2
        widgets.plant_quantity_entry.props.text = new_quantity
        update_gui()
        self.editor.handle_response(gtk.RESPONSE_OK)

        # there should only be three plants,
        new_plant = self.session.query(Plant).\
            filter(Plant.code != self.plant.code).first()
        # test the quantity was set properly on the new plant
        assert new_plant.quantity == new_quantity, new_plant.quantity
        self.session.refresh(self.plant)
        # test the quantity is updated on the original plant
        assert self.plant.quantity == quantity - new_plant.quantity, \
            "%s == %s - %s" % (plant.quantity, quantity, new_plant.quantity)
        # test the quantity for the change is the same as the quantity
        # for the plant
        assert new_plant.changes[0].quantity == new_plant.quantity, \
            "%s == %s" % (new_plant.changes[0].quantity, new_plant.quantity)
        # test the parent_plant for the change is the same as the
        # original plant
        assert new_plant.changes[0].parent_plant == self.plant, \
            'change.parent_plant != original plant'
    def test_location_editor(self):
        loc = self.create(Location, name=u'some site', code=u'STE')
        self.session.commit()
        editor = LocationEditor(model=loc)
        update_gui()
        widgets = editor.presenter.view.widgets

        # test that the accept buttons are NOT sensitive since nothing
        # has changed and that the text entries and model are the same
        assert widgets.loc_name_entry.get_text() == loc.name
        assert widgets.loc_code_entry.get_text() == loc.code
        assert not widgets.loc_ok_button.props.sensitive
        assert not widgets.loc_next_button.props.sensitive

        # test the accept buttons become sensitive when the name entry
        # is changed
        widgets.loc_name_entry.set_text('something')
        update_gui()
        assert widgets.loc_ok_button.props.sensitive
        assert widgets.loc_ok_and_add_button.props.sensitive
        assert widgets.loc_next_button.props.sensitive

        # test the accept buttons become NOT sensitive when the code
        # entry is empty since this is a required field
        widgets.loc_code_entry.set_text('')
        update_gui()
        assert not widgets.loc_ok_button.props.sensitive
        assert not widgets.loc_ok_and_add_button.props.sensitive
        assert not widgets.loc_next_button.props.sensitive

        # test the accept buttons aren't sensitive from setting the textview
        import gtk
        buff = gtk.TextBuffer()
        buff.set_text('saasodmadomad')
        widgets.loc_desc_textview.set_buffer(buff)
        assert not widgets.loc_ok_button.props.sensitive
        assert not widgets.loc_ok_and_add_button.props.sensitive
        assert not widgets.loc_next_button.props.sensitive

        # commit the changes and cleanup
        editor.model.name = editor.model.code = u'asda'
        editor.handle_response(gtk.RESPONSE_OK)
        editor.session.close()
        editor.presenter.cleanup()
        del editor

        assert utils.gc_objects_by_type('LocationEditor') == [], \
            'LocationEditor not deleted'
        assert utils.gc_objects_by_type('LocationEditorPresenter') == [], \
            'LocationEditorPresenter not deleted'
        assert utils.gc_objects_by_type('LocationEditorView') == [], \
            'LocationEditorView not deleted'
    def test_bulk_plant_editor(self):
        """
        Test creating multiple plants with the plant editor.
        """
        try:
            import gtk
        except ImportError:
            raise SkipTest('could not import gtk')
        # use our own plant because PlantEditor.commit_changes() will
        # only work in bulk mode when the plant is in session.new
        p = Plant(accession=self.accession, location=self.location, code=u'2',
                  quantity=52)
        self.editor = PlantEditor(model=p)
        #editor.start()
        update_gui()
        rng = '2,3,4-6'

        for code in utils.range_builder(rng):
            q = self.session.query(Plant).join('accession').\
                filter(and_(Accession.id==self.plant.accession.id,
                            Plant.code==utils.utf8(code)))
            self.assert_(not q.first(), 'code already exists')

        widgets = self.editor.presenter.view.widgets
        # make sure the entry gets a Problem added to it if an
        # existing plant code is used in bulk mode
        widgets.plant_code_entry.set_text('1,' + rng)
        widgets.plant_quantity_entry.set_text('2')
        update_gui()
        problem = (self.editor.presenter.PROBLEM_DUPLICATE_PLANT_CODE,
                   self.editor.presenter.view.widgets.plant_code_entry)
        self.assert_(problem in self.editor.presenter.problems,
                     'no problem added for duplicate plant code')

        # create multiple plant codes
        widgets.plant_code_entry.set_text(rng)
        update_gui()
        self.editor.handle_response(gtk.RESPONSE_OK)

        for code in utils.range_builder(rng):
            q = self.session.query(Plant).join('accession').\
                filter(and_(Accession.id==self.plant.accession.id,
                            Plant.code==utils.utf8(code)))
            self.assert_(q.first(), 'plant %s.%s not created' % \
                            (self.accession, code))