示例#1
0
 def test_agilo_properties(self):
     """Tests the TicketSystem for the agilo properties"""
     ats = AgiloTicketSystem(self.env)
     calc, allowed, sorting, showing = ats.get_agilo_properties(Type.TASK)
     
     # Tests are a bit hard but necessary, every time someone changes the 
     # default properties this will fail, needs to be updated
     self.assert_equals({}, calc, 
                      "Found calculated properties for task: %s" % calc)
     self.assert_equals({}, allowed,
                      "Found allowed link properties for task: %s" % allowed)
     self.assert_equals({}, sorting,
                      "Found sorting properties for task: %s" % sorting)
     self.assert_equals({}, showing,
                      "Found showing properties for task: %s" % showing)
     
     # Now tests a story
     calc, allowed, sorting, showing = ats.get_agilo_properties(Type.USER_STORY)
     
     # Tests are a bit hard but necessary, every time someone changes the 
     # default properties this will fail, needs to be updated
     self.assert_true(Key.TOTAL_REMAINING_TIME in calc and Key.ESTIMATED_REMAINING_TIME in calc, 
                      "Wrong calculated properties for story: %s" % calc)
     self.assert_true(Type.TASK in allowed,
                      "Wrong allowed link properties for story: %s" % allowed)
     self.assert_true(Type.TASK in sorting,
                      "Wrong sorting properties for story: %s" % sorting)
     self.assert_true(Type.TASK in showing,
                      "Wrong showing properties for story: %s" % showing)
示例#2
0
文件: admin.py 项目: nagyist/agilo
 def detail_view(self, req, cat, page, link):
     links_configuration = LinksConfiguration(self.env)
     (source, target) = links_configuration.extract_types(link)
     copy_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.COPY),
                                                      default='').split(',')]
     show_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.SHOW),
                                                      default='').split(',')]
     ticket_system = AgiloTicketSystem(self.env)
     # dict of name->label for all core and custom fields
     labels = dict([(f['name'], f['label'])
                    for f in ticket_system.get_ticket_fields()])
     cascade_delete = source + '-' + target in self._get_delete_pairs()
     data = {
         'view': 'detail',
         'link': link,
         'source': source,
         'target': target,
         'source_fields': self.config.TYPES[source],
         'target_fields': self.config.TYPES[target],
         'labels': labels,
         'copy_fields': copy_fields,
         'show_fields': show_fields,
         'cascade_delete': cascade_delete
     }
     return 'agilo_admin_links.html', data
示例#3
0
文件: admin.py 项目: djangsters/agilo
 def detail_view(self, req, cat, page, link):
     links_configuration = LinksConfiguration(self.env)
     (source, target) = links_configuration.extract_types(link)
     copy_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.COPY), 
                                                      default='').split(',')]
     show_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                      (source, target, LinkOption.SHOW), 
                                                      default='').split(',')]
     ticket_system = AgiloTicketSystem(self.env)
     # dict of name->label for all core and custom fields
     labels = dict([(f['name'], f['label']) for f in ticket_system.get_ticket_fields()])
     cascade_delete = source+'-'+target in self._get_delete_pairs()
     data = {
         'view': 'detail',
         'link': link,
         'source' : source,
         'target' : target,
         'source_fields' : self.config.TYPES[source],
         'target_fields' : self.config.TYPES[target],
         'labels' : labels,
         'copy_fields' : copy_fields,
         'show_fields' : show_fields,
         'cascade_delete': cascade_delete
     }
     return 'agilo_admin_links.html', data
示例#4
0
文件: model.py 项目: nagyist/agilo
 def save(self, db=None):
     """Override save to reset ticket fields in the ticket system"""
     result = super(Sprint, self).save(db=db)
     # Reset the fields for trac 0.11.2
     from agilo.ticket.api import AgiloTicketSystem
     ats = AgiloTicketSystem(self.env)
     if hasattr(ats, 'reset_ticket_fields'):
         ats.reset_ticket_fields()
     return result
示例#5
0
文件: model.py 项目: nagyist/agilo
    def save(self, db=None):
        """Override save to reset ticket fields in the ticket system"""
        result = super(Sprint, self).save(db=db)
        # Reset the fields for trac 0.11.2
        from agilo.ticket.api import AgiloTicketSystem

        ats = AgiloTicketSystem(self.env)
        if hasattr(ats, "reset_ticket_fields"):
            ats.reset_ticket_fields()
        return result
示例#6
0
文件: web_ui.py 项目: nagyist/agilo
    def _hide_fields_not_configured_for_this_type(self, req, data):
        ticket_type = req.args[Key.TYPE]
        ats = AgiloTicketSystem(self.env)
        normalized_type = ats.normalize_type(ticket_type)
        data[Key.TYPE] = normalized_type
        fields_for_type = AgiloConfig(self.env).TYPES.get(normalized_type, [])
        create_perms = CoreTemplateProvider(self.env).create_permissions(req)

        if normalized_type in create_perms:
            for data_field in data['fields']:
                field_name = data_field[Key.NAME]
                if field_name == Key.TYPE:
                    current_options = data_field.get('options', [])
                    data_field['options'] = \
                        self._ticket_types_the_user_can_create_or_modify(normalized_type, current_options, create_perms)
                    data['type_selection'] = data_field
                    data_field[Key.SKIP] = True
                elif not field_name in fields_for_type:
                    # Skip the field and the value if it's not for this type
                    data_field[Key.SKIP] = True
                elif data_field[Key.SKIP] and (field_name
                                               not in MANDATORY_FIELDS):
                    # We have to make all fields visible which belong to
                    # this ticket type. Unfortunately, Trac just creates
                    # a Ticket (though an AgiloTicket due to our monkey
                    # patching) and we can't influence the instantiation
                    # itself.
                    # Therefore it just depends on the default ticket type
                    # set in the environment what fields this ticket has.
                    # Therefore some fields are marked skipped although they
                    # should be displayed.
                    # trac itself skips some fields because it want to have
                    # more control over the positioning. We have to respect
                    # that.

                    # fs, 04.11.2008: I thought about moving this condition
                    #  to_prepare_fields where I think this code should live
                    # but then I would have to copy all the conditions and
                    # probably the code is here for a good reason so I'm
                    # just adding it here.
                    data_field[Key.SKIP] = False
                elif field_name == Key.OWNER and ats.restrict_owner:
                    # we need to transform the field into a list of users
                    ats.eventually_restrict_owner(data_field)
        elif len(create_perms) > 0:
            # Redirect to the first allowed type for the given user.
            first_allowed_type = create_perms[0]
            req.redirect(req.href.newticket(type=first_allowed_type))
        else:
            if ticket_type not in AgiloConfig(self.env).ALIASES:
                raise TracError(u"Unkown type '%s'!" % ticket_type)
            raise TracError("You are not allowed to create a %s!" %
                            ticket_type)
        return data
示例#7
0
 def _hide_fields_not_configured_for_this_type(self, req, data):
     ticket_type = req.args[Key.TYPE]
     ats = AgiloTicketSystem(self.env)
     normalized_type = ats.normalize_type(ticket_type)
     data[Key.TYPE] = normalized_type
     fields_for_type = AgiloConfig(self.env).TYPES.get(normalized_type, [])
     create_perms = CoreTemplateProvider(self.env).create_permissions(req)
     
     if normalized_type in create_perms:
         for data_field in data['fields']:
             field_name = data_field[Key.NAME]
             if field_name == Key.TYPE:
                 current_options = data_field.get('options', [])
                 data_field['options'] = \
                     self._ticket_types_the_user_can_create_or_modify(normalized_type, current_options, create_perms)
                 data['type_selection'] = data_field
                 data_field[Key.SKIP] = True
             elif not field_name in fields_for_type:
                 # Skip the field and the value if it's not for this type
                 data_field[Key.SKIP] = True
             elif data_field[Key.SKIP] and (field_name not in MANDATORY_FIELDS):
                 # We have to make all fields visible which belong to 
                 # this ticket type. Unfortunately, Trac just creates 
                 # a Ticket (though an AgiloTicket due to our monkey 
                 # patching) and we can't influence the instantiation 
                 # itself. 
                 # Therefore it just depends on the default ticket type 
                 # set in the environment what fields this ticket has. 
                 # Therefore some fields are marked skipped although they
                 # should be displayed.
                 # trac itself skips some fields because it want to have
                 # more control over the positioning. We have to respect
                 # that.
                 
                 # fs, 04.11.2008: I thought about moving this condition 
                 #  to_prepare_fields where I think this code should live
                 # but then I would have to copy all the conditions and
                 # probably the code is here for a good reason so I'm 
                 # just adding it here.
                 data_field[Key.SKIP] = False
             elif field_name == Key.OWNER and ats.restrict_owner:
                 # we need to transform the field into a list of users
                 ats.eventually_restrict_owner(data_field)
     elif len(create_perms) > 0:
         # Redirect to the first allowed type for the given user.
         first_allowed_type = create_perms[0]
         req.redirect(req.href.newticket(type=first_allowed_type))
     else:
         if ticket_type not in AgiloConfig(self.env).ALIASES:
             raise TracError(u"Unkown type '%s'!" % ticket_type)
         raise TracError("You are not allowed to create a %s!" % ticket_type)
     return data
示例#8
0
 def get_custom_fields(self, field_name=None):
     """
     Returns the custom fields from TicketSystem component.
     Use a field name to find a specific custom field only
     """
     if not field_name:    # return full list
         return AgiloTicketSystem(self.env).get_custom_fields()
     else:                  # only return specific item with cfname
         all = AgiloTicketSystem(self.env).get_custom_fields()
         for item in all:
             if item[Key.NAME] == field_name:
                 return item
         return None        # item not found
示例#9
0
 def _validate_ticket(self, req, ticket, force_collision_check=False):
     if 'ts' in req.args:
         match = re.search('^(\d+)$', req.args.get('ts') or '')
         if match:
             timestamp = int(match.group(1))
             last_changed = datetime.utcfromtimestamp(timestamp).replace(tzinfo=utc)
             req.args['ts'] = str(last_changed)
     ticket_system = AgiloTicketSystem(self.env)
     trac_ticket_system = super(AgiloTicketModule, self)
     
     if ticket_system.is_trac_012():
         return trac_ticket_system._validate_ticket(req, ticket, force_collision_check=force_collision_check)
     return trac_ticket_system._validate_ticket(req, ticket)
示例#10
0
文件: types.py 项目: nagyist/agilo
    def detail_save_view(self, req, cat, page, ticket_type):
        """Save the detail panel view"""
        # The types will be stored in lowercase and the space is not a
        # valid character for the config file key
        ticket_type = normalize_ticket_type(ticket_type)

        alias = req.args.get(Key.ALIAS)
        if alias:
            self.agilo_config.change_option('%s.%s' % (ticket_type, Key.ALIAS),
                                            alias,
                                            section=AgiloConfig.AGILO_TYPES,
                                            save=False)
        # save fields as string or comma-separated list of values
        # FIXME: (AT) after going crazy, it came out that some types are not
        # saved because there is no specific field assigned and the config
        # won't store the property in the trac.ini. So the agilo type will also
        # not be loaded, even if the alias would be set.
        fields = req.args.get(Key.FIELDS, '')
        # We have to save strings not lists
        if isinstance(fields, list):
            fields = ', '.join(fields)
        self.agilo_config.change_option(ticket_type,
                                        fields,
                                        section=AgiloConfig.AGILO_TYPES,
                                        save=False)
        calc = []
        for res, func in zip(req.args.getlist('result'),
                             req.args.getlist('function')):
            if res and func:
                configstring = u'%s=%s' % (res.strip(), func.strip())
                parsed = parse_calculated_field(configstring)
                if parsed == None:
                    msg = u"Wrong format for calculated property '%s'"
                    raise TracError(_(msg) % res)
                calc.append(configstring)
        calc = ','.join(calc)
        if calc:
            self.agilo_config.change_option(
                '%s.%s' % (ticket_type, LinkOption.CALCULATE),
                calc,
                section=AgiloConfig.AGILO_LINKS,
                save=False)
        self.agilo_config.save()

        # on 0.12 we need to reset the ticket fields explicitely as the synchronization
        # is not done with the trac.ini anymore
        if AgiloTicketSystem(self.env).is_trac_012():
            AgiloTicketSystem(self.env).reset_ticket_fields()
        return req.redirect(req.href.admin(cat, page))
示例#11
0
文件: web_ui.py 项目: nagyist/agilo
    def _validate_ticket(self, req, ticket, force_collision_check=False):
        if 'ts' in req.args:
            match = re.search('^(\d+)$', req.args.get('ts') or '')
            if match:
                timestamp = int(match.group(1))
                last_changed = datetime.utcfromtimestamp(timestamp).replace(
                    tzinfo=utc)
                req.args['ts'] = str(last_changed)
        ticket_system = AgiloTicketSystem(self.env)
        trac_ticket_system = super(AgiloTicketModule, self)

        if ticket_system.is_trac_012():
            return trac_ticket_system._validate_ticket(
                req, ticket, force_collision_check=force_collision_check)
        return trac_ticket_system._validate_ticket(req, ticket)
示例#12
0
 def test_non_existent_type(self):
     """Tests that if a type is not defined as agilo type will get all properties"""
     nonex = self.teh.create_ticket('nonex')
     all_fields = AgiloTicketSystem(self.env).get_ticket_fields()
     
     for f1, f2 in zip(nonex.fields, all_fields):
         self.assert_equals(f1, f2, "Error: %s != %s" % (f1, f2))
示例#13
0
 def update_custom_field(self, customfield, create=False):
     """
     Update or create a new custom field (if requested).
     customfield is a dictionary with the following possible keys:
         name = name of field (alphanumeric only)
         type = text|checkbox|select|radio|textarea
         label = label description
         value = default value for field content
         options = options for select and radio types (list, leave first empty for optional)
         cols = number of columns for text area
         rows = number of rows for text area
         order = specify sort order for field
     """
     
     self._validate_input(customfield, create)
     f_type = customfield[Key.TYPE]
     if f_type == 'textarea':
         def set_default_value(key, default):
             if (key not in customfield) or \
                     (not unicode(customfield[key]).isdigit()):
                 customfield[key] = unicode(default)
         # dwt: why is this called twice?
         set_default_value(Key.COLS, 60)
         set_default_value(Key.COLS, 5)
     
     if create:
         number_of_custom_fields = len(self.get_custom_fields())
         # We assume that the currently added custom field is not present in 
         # the return value of get_custom_fields and we start counting from 0
         customfield[Key.ORDER] = str(number_of_custom_fields)
     
     self._store_all_options_for_custom_field(customfield)
     AgiloTicketSystem(self.env).reset_ticket_fields()
示例#14
0
    def test_can_serialize_task_to_dict(self):
        task = AgiloTicket(self.env, t_type=Type.TASK)
        self.assertNotEqual('fixed', task[Key.RESOLUTION])
        task[Key.SUMMARY] = 'My Summary'
        task.insert()
        expected = {
            # required
            Key.ID: task.id,
            Key.TYPE: Type.TASK,
            Key.SUMMARY: 'My Summary',
            Key.DESCRIPTION: '',
            Key.STATUS: '',
            Key.RESOLUTION: '',
            Key.REPORTER: '',
            Key.OWNER: '',
            # type specific
            Key.SPRINT: '',
            Key.REMAINING_TIME: '',
            Key.RESOURCES: '',
            
            # Key.Options is not used in order to reduce required data to 
            # transfer for a backlog load.
            
            'outgoing_links': [],
            'incoming_links': [],
            'time_of_last_change': to_timestamp(task.time_changed),
            'ts': str(task.time_changed),
        }
        if AgiloTicketSystem.is_trac_1_0():
            from trac.util.datefmt import to_utimestamp
            expected.update({'view_time': str(to_utimestamp(task.time_changed))})

        self.assert_equals(expected, task.as_dict())
示例#15
0
    def test_can_serialize_task_to_dict(self):
        task = AgiloTicket(self.env, t_type=Type.TASK)
        self.assertNotEqual('fixed', task[Key.RESOLUTION])
        task[Key.SUMMARY] = 'My Summary'
        task.insert()
        expected = {
            # required
            Key.ID: task.id,
            Key.TYPE: Type.TASK,
            Key.SUMMARY: 'My Summary',
            Key.DESCRIPTION: '',
            Key.STATUS: '',
            Key.RESOLUTION: '',
            Key.REPORTER: '',
            Key.OWNER: '',
            # type specific
            Key.SPRINT: '',
            Key.REMAINING_TIME: '',
            Key.RESOURCES: '',

            # Key.Options is not used in order to reduce required data to
            # transfer for a backlog load.
            'outgoing_links': [],
            'incoming_links': [],
            'time_of_last_change': to_timestamp(task.time_changed),
            'ts': str(task.time_changed),
        }
        if AgiloTicketSystem.is_trac_1_0():
            from trac.util.datefmt import to_utimestamp
            expected.update(
                {'view_time': str(to_utimestamp(task.time_changed))})

        self.assert_equals(expected, task.as_dict())
示例#16
0
 def setUp(self):
     self.super()
     self.env.config.set('components', 'agilo.scrum.backlog.model.backlogupdater', 'disabled')
     self.env.config.set('components', 'agilo.scrum.burndown.changelistener.burndowndatachangelistener', 'disabled')
     # so the changes persist after the shutdown
     self.env.config.save()
     if not AgiloTicketSystem(self.env).is_trac_012():
         self.env.shutdown()
     # restart: so the listeneres that where registered before this test are actually disabled
     self.env = self.testenv.get_trac_environment()
     self.task = self.teh.create_task(sprint=self.sprint_name())
示例#17
0
 def test_fields_for_task(self):
     """Tests how the FieldsWrapper respond with a task type"""
     ticket_system = AgiloTicketSystem(self.env)
     tfw = FieldsWrapper(self.env, 
                         ticket_system.get_ticket_fields(), 
                         Type.TASK)
     
     expected_fields_for_task = AgiloConfig(self.env).TYPES.get(Type.TASK)
     # Try to check the keys
     field_wrapper_names = map(lambda field: field[Key.NAME], tfw)
     
     # it is added by the ticket system to store sprint
     # scope synchronous with milestone
     field_wrapper_names.remove(Key.MILESTONE)
     expected_fields_for_task.remove('id')
     if not ticket_system.is_trac_012():
         # in Trac 0.11, time fields are magic
         field_wrapper_names.append('changetime')
         field_wrapper_names.append('time')
     self.assert_equals(sorted(expected_fields_for_task), sorted(field_wrapper_names))
示例#18
0
 def test_safe_custom_fields(self):
     """Tests that the defined custom fields are safe"""
     ticket_custom = \
         AgiloConfig(self.env).get_section(AgiloConfig.TICKET_CUSTOM)
     custom_fields = ticket_custom.get_options_matching_re('^[^.]+$')
     tfw = FieldsWrapper(self.env, 
                         AgiloTicketSystem(self.env).get_ticket_fields(), 
                         Type.TASK)
     for f in tfw:
         if f[Key.NAME] in custom_fields:
             self.assert_true(f[Key.CUSTOM], 
                             "%s should be custom!!!" % f[Key.NAME])
示例#19
0
 def interesting_fieldnames(self):
     fieldnames = []
     for field in AgiloTicketSystem(self.env).get_ticket_fields():
         fieldname = field[Key.NAME]
         # AT: here key must be a string or will break the call
         # afterwards
         try:
             fieldname = str(fieldname)
         except ValueError, e:
             warning(self, "Fieldname: %s is not a string... %s" % \
                     (repr(fieldname), exception_to_unicode(e)))
             continue
         fieldnames.append(fieldname)
示例#20
0
 def runTest(self):
     """Tests the ticket delete method"""
     self._tester.login_as(Usernames.admin)
     ticket_id = self._tester.create_new_agilo_userstory('Delete Me')
     self._tester.go_to_view_ticket_page(ticket_id)
     tc.formvalue('propertyform', 'delete', 'click')
     tc.submit('delete')
     self._tester.go_to_view_ticket_page(ticket_id, should_fail=True)
     tc.code(404)
     from agilo.ticket import AgiloTicketSystem
     if AgiloTicketSystem.is_trac_1_0():
         return
     else:
         self._tester._set_ticket_id_sequence(new_value=self._tester.ticketcount)
示例#21
0
 def runTest(self):
     """Tests the ticket delete method"""
     self._tester.login_as(Usernames.admin)
     ticket_id = self._tester.create_new_agilo_userstory('Delete Me')
     self._tester.go_to_view_ticket_page(ticket_id)
     tc.formvalue('propertyform', 'delete', 'click')
     tc.submit('delete')
     self._tester.go_to_view_ticket_page(ticket_id, should_fail=True)
     tc.code(404)
     from agilo.ticket import AgiloTicketSystem
     if AgiloTicketSystem.is_trac_1_0():
         return
     else:
         self._tester._set_ticket_id_sequence(
             new_value=self._tester.ticketcount)
示例#22
0
 def delete_custom_field(self, field_name):
     """Deletes a custom field"""
     if not self.ticket_custom.get(field_name):
         return # Nothing to do here - cannot find field
     # Need to redo the order of fields that are after the field to be deleted
     order_to_delete = self.ticket_custom.get_int('%s.%s' % (field_name, Key.ORDER))
     cfs = self.get_custom_fields()
     for field in cfs:
         if field[Key.ORDER] > order_to_delete:
             field[Key.ORDER] -= 1
             self._set_custom_field_value(field, Key.ORDER)
         elif field[Key.NAME] == field_name:
             # Remove any data for the custom field (covering all bases)
             self._del_custom_field_value(field)
     # Save settings
     self.ticket_custom.save()
     AgiloTicketSystem(self.env).reset_ticket_fields()
示例#23
0
 def runTest(self):
     # Setting the a default type different from the ticket type to be 
     # created triggered another bug in the preview display...
     self._tester.login_as(Usernames.admin)
     
     self._tester.login_as(Usernames.product_owner)
     title = 'Foo Bar Title'
     ticket_id = self._tester.create_new_agilo_userstory(title)
     self._tester.go_to_view_ticket_page(ticket_id)
     
     new_title = 'bulb'
     tc.formvalue('propertyform', 'summary', new_title)
     tc.submit('preview')
     
     tc.code(200)
     from agilo.ticket.api import AgiloTicketSystem
     if AgiloTicketSystem.is_trac_1_0():
         tc.find('<span[^>]*>%s</span>' % new_title)
     else:
         tc.find('<h2[^>]*>%s</h2>' % new_title)
示例#24
0
    def runTest(self):
        # Setting the a default type different from the ticket type to be
        # created triggered another bug in the preview display...
        self._tester.login_as(Usernames.admin)

        self._tester.login_as(Usernames.product_owner)
        title = 'Foo Bar Title'
        ticket_id = self._tester.create_new_agilo_userstory(title)
        self._tester.go_to_view_ticket_page(ticket_id)

        new_title = 'bulb'
        tc.formvalue('propertyform', 'summary', new_title)
        tc.submit('preview')

        tc.code(200)
        from agilo.ticket.api import AgiloTicketSystem
        if AgiloTicketSystem.is_trac_1_0():
            tc.find('<span[^>]*>%s</span>' % new_title)
        else:
            tc.find('<h2[^>]*>%s</h2>' % new_title)
示例#25
0
    def _create_environment(self, env_dir, db_url, repo_type, repodir):
        if self._running_on_windows():
            # On Windows we need to double-escape backslashes - otherwise they
            # will be used as escape characters when storing the config (repo
            # dir in trac.ini won't contain any backslashes then).
            repodir = repodir.replace('\\', '\\\\')

        self._create_database(db_url)
        self._tracadmin('initenv', env_dir, db_url, repo_type, repodir)
        env = self.get_trac_environment()
        config = env.config
        for component in self.get_enabled_components():
            config.set('components', component, 'enabled')
        for component in self.get_disabled_components():
            config.set('components', component, 'disabled')
        for (section, name, value) in self.get_config_options():
            config.set(section, name, value)
        config.save()
        config.touch()
        if not AgiloTicketSystem(env).is_trac_012():
            env.shutdown()
示例#26
0
    def test_owner_team_member_with_sprint_related_tickets(self):
        """
        Tests that the owner of a sprint related ticket, in case of restrict_owner
        option, is limited to the team members assigned to the sprint, in case the
        ticket has the Remaining Time property
        """
        teh = self.teh
        env = self.env
        self.assert_true(AgiloTicketSystem(env).restrict_owner)
        t = teh.create_team('A-Team')
        self.assert_true(t.save())
        s = teh.create_sprint('Test Me', team=t)
        self.assert_equals('Test Me', s.name)
        self.assert_equals(s.team, t)
        tm1 = teh.create_member('TM1', t)
        self.assert_true(tm1.save())
        tm2 = teh.create_member('TM2', t)
        self.assert_true(tm2.save())
        tm3 = teh.create_member('TM3')
        self.assert_true(tm3.save())

        self.assert_contains(tm1.name, [m.name for m in t.members])
        self.assert_contains(tm2.name, [m.name for m in t.members])

        # Now make a ticket that is dependent from the sprint
        task = teh.create_ticket(Type.TASK,
                                 props={
                                     Key.REMAINING_TIME: '12.5',
                                     Key.OWNER: tm1.name,
                                     Key.SPRINT: s.name
                                 })
        self.assert_equals(s.name, task[Key.SPRINT])
        f = task.get_field(Key.OWNER)
        self.assert_true(tm1.name in f[Key.OPTIONS])
        self.assert_true(tm2.name in f[Key.OPTIONS])
        self.assert_false(tm3.name in f[Key.OPTIONS])
示例#27
0
 def interesting_fieldnames(self):
     fieldnames = [Key.ID, 'ticket']
     for field in AgiloTicketSystem(self.env).get_ticket_fields():
         fieldname = field[Key.NAME]
         fieldnames.append(fieldname)
     return fieldnames
示例#28
0
 def _bug_calculated_properties(self):
     return AgiloTicketSystem(self.env).get_agilo_properties('bug')[0].keys()
示例#29
0
 def test_can_map_alias_to_trac_type(self):
     ticket_system = AgiloTicketSystem(self.env)
     self.assert_equals(Type.TASK, ticket_system.normalize_type(Type.TASK))
     self.assert_equals(Type.TASK, ticket_system.normalize_type('Task')) #Task alias
示例#30
0
文件: api.py 项目: nagyist/agilo
 def tearDown(self):
     if not AgiloTicketSystem(self.env).is_trac_012():
         self.env.shutdown()
     self.testenv.remove()
     self.super()
示例#31
0
 def _previous_type_had_field(self, fieldname, old_values):
     previous_type = old_values[Key.TYPE]
     ticket_system = AgiloTicketSystem(self.env)
     return fieldname in ticket_system.get_ticket_fieldnames(previous_type)
示例#32
0
 def test_knows_which_fieldnames_are_valid_for_a_ticket_type(self):
     ticket_system = AgiloTicketSystem(self.env)
     self.assert_contains(Key.REMAINING_TIME, ticket_system.get_ticket_fieldnames(Type.TASK))
     self.assert_not_contains(Key.BUSINESS_VALUE, ticket_system.get_ticket_fieldnames(Type.TASK))
示例#33
0
 def test_just_return_input_if_no_alias_was_found(self):
     ticket_system = AgiloTicketSystem(self.env)
     self.assert_none(ticket_system.normalize_type('nonexisting_type'))
示例#34
0
 def _previous_type_had_field(self, fieldname, old_values):
     previous_type = old_values[Key.TYPE]
     ticket_system = AgiloTicketSystem(self.env)
     return fieldname in ticket_system.get_ticket_fieldnames(previous_type)