コード例 #1
0
ファイル: functional.py プロジェクト: pkdevbox/trac
    def runTest(self):
        """Add a user to a permissions group"""
        self._tester.go_to_admin("Permissions")
        tc.find('Manage Permissions')
        tc.formvalue('addsubj', 'sg_subject', 'authenticated')
        tc.formvalue('addsubj', 'sg_group', 'somegroup')
        tc.submit()
        authenticated = unicode_to_base64('authenticated')
        somegroup = unicode_to_base64('somegroup')
        tc.find('%s:%s' % (authenticated, somegroup))

        revoke_checkbox = '%s:%s' % (unicode_to_base64('anonymous'),
                                     unicode_to_base64('PERMISSION_GRANT'))
        tc.formvalue('addperm', 'gp_subject', 'anonymous')
        tc.formvalue('addperm', 'action', 'PERMISSION_GRANT')
        tc.submit()
        tc.find(revoke_checkbox)
        self._testenv.get_trac_environment().config.touch()
        self._tester.logout()
        self._tester.go_to_admin("Permissions")
        try:
            tc.formvalue('addsubj', 'sg_subject', 'someuser')
            tc.formvalue('addsubj', 'sg_group', 'authenticated')
            tc.submit()
            tc.find("The subject someuser was not added to the "
                    "group authenticated because the group has "
                    "TICKET_CHGPROP permission and users cannot "
                    "grant permissions they don't possess.")
        finally:
            self._tester.login('admin')
            self._tester.go_to_admin("Permissions")
            tc.formvalue('revokeform', 'sel', revoke_checkbox)
            tc.submit()
            tc.notfind(revoke_checkbox)
コード例 #2
0
ファイル: functional.py プロジェクト: exocad/exotrac
 def runTest(self):
     """Test for regression of http://trac.edgewall.org/ticket/11069
     The permissions list should only be populated with permissions that
     the user can grant."""
     self._tester.go_to_front()
     self._tester.logout()
     self._tester.login('user')
     self._testenv.grant_perm('user', 'PERMISSION_GRANT')
     env = self._testenv.get_trac_environment()
     from trac.perm import PermissionSystem
     user_perms = PermissionSystem(env).get_user_permissions('user')
     all_actions = PermissionSystem(env).get_actions()
     try:
         self._tester.go_to_admin("Permissions")
         for action in all_actions:
             option = r"<option>%s</option>" % action
             if action in user_perms and user_perms[action] is True:
                 tc.find(option)
             else:
                 tc.notfind(option)
     finally:
         self._testenv.revoke_perm('user', 'PERMISSION_GRANT')
         self._tester.go_to_front()
         self._tester.logout()
         self._tester.login('admin')
コード例 #3
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Set preferences for admin user"""
     self._tester.go_to_preferences()
     try:
         tc.notfind('Your preferences have been saved.')
         tc.formvalue('userprefs', 'name', ' System Administrator ')
         tc.formvalue('userprefs', 'email', ' [email protected] ')
         tc.submit()
         tc.find('Your preferences have been saved.')
         self._tester.go_to_preferences("Localization")
         tc.formvalue('userprefs', 'tz', 'GMT -10:00')
         tc.submit()
         tc.find('Your preferences have been saved.')
         self._tester.go_to_preferences()
         tc.notfind('Your preferences have been saved.')
         tc.find('value="System Administrator"')
         tc.find(r'value="admin@example\.com"')
         self._tester.go_to_preferences("Localization")
         tc.find('GMT -10:00')
     finally:
         self._tester.go_to_preferences()
         tc.formvalue('userprefs', 'name', '')
         tc.formvalue('userprefs', 'email', '')
         tc.submit()
         tc.find('Your preferences have been saved.')
コード例 #4
0
ファイル: ticket_gui_test.py プロジェクト: djangsters/agilo
 def runTest(self):
     self._tester.login_as(Usernames.team_member)
     self._tester.go_to_new_ticket_page(Type.TASK)
     tc.formvalue('propertyform', 'summary', 'Foo Summary')
     tc.submit('preview')
     tc.notfind('Business Value Points')
     tc.notfind('User Story Priority')
コード例 #5
0
ファイル: admin.py プロジェクト: pkdevbox/trac
    def runTest(self):
        """Admin modify priority details"""
        name = "DetailPriority"
        # Create a priority
        self._tester.create_priority(name + '1')

        # Modify the details of the priority
        priority_url = self._tester.url + "/admin/ticket/priority"
        tc.go(priority_url)
        tc.url(priority_url + '$')
        tc.follow(name + '1')
        tc.url(priority_url + '/' + name + '1')
        tc.formvalue('edit', 'name', name + '2')
        tc.submit('save')
        tc.url(priority_url + '$')

        # Cancel more modifications
        tc.go(priority_url)
        tc.follow(name)
        tc.formvalue('edit', 'name', name + '3')
        tc.submit('cancel')
        tc.url(priority_url + '$')

        # Verify that only the correct modifications show up
        tc.notfind(name + '1')
        tc.find(name + '2')
        tc.notfind(name + '3')
コード例 #6
0
ファイル: testcases.py プロジェクト: pkdevbox/trac
    def runTest(self):
        """Test for regression of http://trac.edgewall.org/ticket/7209"""
        ticketid = self._tester.create_ticket()
        self._tester.create_ticket()
        self._tester.add_comment(ticketid)
        self._tester.attach_file_to_ticket(ticketid, filename='hello.txt',
                                           description='Preserved Descr')
        self._tester.go_to_ticket(ticketid)
        tc.find('Preserved Descr')
        # Now replace the existing attachment, and the description should come
        # through.
        self._tester.attach_file_to_ticket(ticketid, filename='hello.txt',
                                           description='', replace=True)
        self._tester.go_to_ticket(ticketid)
        tc.find('Preserved Descr')

        self._tester.attach_file_to_ticket(ticketid, filename='blah.txt',
                                           description='Second Attachment')
        self._tester.go_to_ticket(ticketid)
        tc.find('Second Attachment')

        # This one should get a new description when it's replaced
        # (Second->Other)
        self._tester.attach_file_to_ticket(ticketid, filename='blah.txt',
                                           description='Other Attachment',
                                           replace=True)
        self._tester.go_to_ticket(ticketid)
        tc.find('Other Attachment')
        tc.notfind('Second Attachment')
コード例 #7
0
ファイル: testcases.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Regression test for non-ascii usernames (#6318)
     """
     # first do a logout, otherwise we might end up logged in as
     # admin again, as this is the first thing the tester does.
     # ... but even before that we need to make sure we're coming
     # from a valid URL, which is not the case if we're just coming
     # from the above test! ('/wiki/\xE9t\xE9')
     self._tester.go_to_front()
     self._tester.logout()
     try:
         # also test a regular ascii user name
         self._testenv.adduser(u'user')
         self._tester.login(u'user')
         self._tester.go_to_front()
         self._tester.logout()
         # now test utf-8 user name
         self._testenv.adduser(u'joé')
         self._tester.login(u'joé')
         self._tester.go_to_front()
         # when failed to retrieve session, FakeSession() and FakePerm()
         # are used and the req.perm has no permissions.
         tc.notfind(internal_error)
         tc.notfind("You don't have the required permissions")
         self._tester.logout()
         # finally restore expected 'admin' login
         self._tester.login('admin')
     finally:
         self._testenv.deluser(u'joé')
コード例 #8
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     self._tester.go_to_admin("Basic Settings")
     pytz_hint = "Install pytz for a complete list of timezones."
     from trac.util.datefmt import pytz
     if pytz is None:
         tc.find(pytz_hint)
     else:
         tc.notfind(pytz_hint)
コード例 #9
0
ファイル: admin.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Admin remove component"""
     name = "RemovalComponent"
     self._tester.create_component(name)
     component_url = self._tester.url + "/admin/ticket/components"
     tc.go(component_url)
     tc.formvalue('component_table', 'sel', name)
     tc.submit('remove')
     tc.notfind(name)
コード例 #10
0
ファイル: functional.py プロジェクト: exocad/exotrac
 def runTest(self):
     default_handler = self._testenv.get_config("trac", "default_handler")
     self._testenv.set_config("trac", "default_handler", "PreferencesModule")
     try:
         tc.go(self._tester.url)
         tc.notfind(internal_error)
         tc.find(r"\bPreferences\b")
     finally:
         self._testenv.set_config("trac", "default_handler", default_handler)
コード例 #11
0
ファイル: import_test.py プロジェクト: djangsters/agilo
 def runTest(self):
     binary_data = '\xcf\xd0\xe0\x11\xb1\xa1\xe1\x1a\x00\x00'
     self._tester.upload_csv_for_import(binary_data, file_encoding=None)
     tc.find('<h1>Import Preview</h1>')
     
     tc.find('<strong>Warning:</strong>')
     tc.notfind('businessvalue')
     tc.notfind(u'Umlaut check äöü'.encode('UTF-8'))
     tc.find("Import not available, errors detected.")
コード例 #12
0
ファイル: admin.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Admin remove version"""
     name = "VersionRemove"
     self._tester.create_version(name)
     version_url = self._tester.url + "/admin/ticket/versions"
     tc.go(version_url)
     tc.formvalue('version_table', 'sel', name)
     tc.submit('remove')
     tc.url(version_url + '$')
     tc.notfind(name)
コード例 #13
0
ファイル: admin.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Admin create duplicate component"""
     name = "DuplicateComponent"
     self._tester.create_component(name)
     component_url = self._tester.url + "/admin/ticket/components"
     tc.go(component_url)
     tc.formvalue('addcomponent', 'name', name)
     tc.submit()
     tc.notfind(internal_error)
     tc.find('Component .* already exists')
コード例 #14
0
ファイル: ticket_gui_test.py プロジェクト: djangsters/agilo
 def runTest(self):
     team_name = 'NewTasksWithRestrictOwnerTeam'
     sprint_name = 'NewTasksWithRestrictOwnerSprint'
     self._set_restrict_owner_option('true')
     self._create_sprint_with_team_and_team_member(sprint_name, team_name)
     self._tester.login_as(Usernames.team_member)
     self._tester.go_to_new_ticket_page(Type.TASK)
     tc.notfind('<input type="text" id="field-owner" name="field_owner"')
     self._tester.create_new_agilo_task('Foo Bar', sprint=sprint_name, 
                                        restrict_owner=True)
コード例 #15
0
ファイル: ticket_gui_test.py プロジェクト: djangsters/agilo
 def runTest(self):
     self._tester.login_as(Usernames.scrum_master)
     t_id = self._tester.create_new_agilo_task('Type should not be set')
     #Now go to edit page and save.
     self._tester.go_to_view_ticket_page(t_id)
     tc.fv('propertyform', 'submit', 'click')
     tc.submit('submit')
     # Now check that in the view page there is not type set to Task
     tc.notfind("<li>\s*<strong>type</strong>\s*set to\s*<em>Task</em>\s*</li>", 
                flags='ims')
コード例 #16
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Remove a user from a permissions group"""
     self._tester.go_to_admin("Permissions")
     tc.find('Manage Permissions')
     authenticated = unicode_to_base64('authenticated')
     somegroup = unicode_to_base64('somegroup')
     tc.find('%s:%s' % (authenticated, somegroup))
     tc.formvalue('revokeform', 'sel', '%s:%s' % (authenticated, somegroup))
     tc.submit()
     tc.notfind('%s:%s' % (authenticated, somegroup))
コード例 #17
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Test for regression of http://trac.edgewall.org/ticket/11777
     fix for raw revisions in search results.
     """
     self._testenv.svn_mkdir(["ticket11777"], "")
     rev = self._testenv.svn_add("ticket11777/file1.txt", "data", "ticket-11777")
     tc.go(self._tester.url + "/search?q=ticket-11777&noquickjump=1&changeset=on")
     tc.notfind(r"\[%010d\]: ticket-11777" % rev)
     tc.find(r"\[%d\]: ticket-11777" % rev)
     tc.find(' href="/changeset/%d"' % rev)
コード例 #18
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     default_handler = self._testenv.get_config('trac', 'default_handler')
     self._testenv.set_config('trac', 'default_handler',
                              'PreferencesModule')
     try:
         tc.go(self._tester.url)
         tc.notfind(internal_error)
         tc.find(r"\bPreferences\b")
     finally:
         self._testenv.set_config('trac', 'default_handler',
                                  default_handler)
コード例 #19
0
ファイル: admin.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Admin create duplicate version"""
     name = "DuplicateVersion"
     self._tester.create_version(name)
     version_admin = self._tester.url + "/admin/ticket/versions"
     tc.go(version_admin)
     tc.url(version_admin)
     tc.formvalue('addversion', 'name', name)
     tc.submit()
     tc.notfind(internal_error)
     tc.find('Version "%s" already exists.' % name)
コード例 #20
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Test for regression of http://trac.edgewall.org/ticket/5765
     Unable to turn off 'Enable access keys' in Preferences
     """
     self._tester.go_to_preferences("Keyboard Shortcuts")
     tc.formvalue('userprefs', 'accesskeys', True)
     tc.submit()
     tc.find('name="accesskeys".*checked="checked"')
     tc.formvalue('userprefs', 'accesskeys', False)
     tc.submit()
     tc.notfind('name="accesskeys".*checked="checked"')
コード例 #21
0
ファイル: import_test.py プロジェクト: djangsters/agilo
 def runTest(self):
     self._tester.login_as(Usernames.product_owner)
     self._tester.upload_csv_for_import(GOOD_CSV_DATA, 'UTF-8')
     tc.find('<h1>Import Preview</h1>')
     
     # Select one form for twill
     tc.formvalue('cancel_import', 'cancel', '1')
     tc.submit('Cancel')
     
     tc.notfind('<strong>Warning:</strong>')
     tc.find('<h1>Import New Tickets from CSV</h1>')
コード例 #22
0
 def runTest(self):
     self._tester.login_as(Usernames.product_owner)
     # create two tickets
     ticket_info = self._tester.perform_import(GOOD_CSV_DATA)
     csv_delete_data = self._tester.build_csv_for_ticket_deletion_from(ticket_info)
     
     encoding = self._tester.upload_csv_for_delete_import(csv_delete_data)
     tc.find('<h1>Delete Preview</h1>')
     tc.find('File contents read with encoding <b>%s</b>.' % encoding)
     tc.notfind('businessvalue')
     tc.notfind('keywords')
コード例 #23
0
    def runTest(self):
        self.tester.login_as(Usernames.admin)
        tc.go("backlog/Sprint%20Backlog?bscope=non-existing-sprint")
        tc.code(500)
        tc.find("Invalid Sprint name")
        try:
            tc.notfind("trac.edgewall.org/newticket")
        except TwillAssertionError:
            raise Exception("Found a link to the official trac bug tracking platform")

        tc.find("trac-hacks.org/newticket")
コード例 #24
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Remove a permissions group"""
     self._tester.go_to_admin("Permissions")
     tc.find('Manage Permissions')
     somegroup = unicode_to_base64('somegroup')
     REPORT_CREATE = unicode_to_base64('REPORT_CREATE')
     tc.find('%s:%s' % (somegroup, REPORT_CREATE))
     tc.formvalue('revokeform', 'sel', '%s:%s' % (somegroup, REPORT_CREATE))
     tc.submit()
     tc.notfind('%s:%s' % (somegroup, REPORT_CREATE))
     tc.notfind(somegroup)
コード例 #25
0
ファイル: dashboard_test.py プロジェクト: djangsters/agilo
 def runTest(self):
     self._tester.login_as(Usernames.product_owner)
     dashboard_url = self._tester.url + DASHBOARD_URL
     tc.go(dashboard_url)
     tc.code(200)
     
     self._tester.logout()
     tc.go(dashboard_url)
     tc.code(403)
     
     self._tester.go_to_front()
     tc.notfind('href="%s"' % DASHBOARD_URL)
コード例 #26
0
ファイル: functional.py プロジェクト: exocad/exotrac
 def runTest(self):
     """Test for regression of http://trac.edgewall.org/ticket/11777
     fix for raw revisions in search results.
     """
     self._testenv.svn_mkdir(['ticket11777'], '')
     rev = self._testenv.svn_add('ticket11777/file1.txt', 'data',
                                 'ticket-11777')
     tc.go(self._tester.url +
           '/search?q=ticket-11777&noquickjump=1&changeset=on')
     tc.notfind(r'\[%010d\]: ticket-11777' % rev)
     tc.find(r'\[%d\]: ticket-11777' % rev)
     tc.find(' href="/changeset/%d"' % rev)
コード例 #27
0
ファイル: functional.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Check empty repository"""
     browser_url = self._tester.url + "/browser"
     tc.go(browser_url)
     tc.url(browser_url)
     # This tests the current behavior; I'm not sure it's the best
     # behavior.
     tc.follow("Last Change")
     tc.find("Error: No such changeset")
     tc.back()
     tc.follow("Revision Log")
     tc.notfind("Error: Nonexistent path")
コード例 #28
0
    def runTest(self):
        self._tester.login_as(Usernames.team_member)
        ticket_id = self._tester.create_new_agilo_task('some task')
        self._tester.accept_ticket(ticket_id)
        
        self._tester.login_as(Usernames.second_team_member)
        self._tester.go_to_view_ticket_page(ticket_id, should_fail=True)
        tc.notfind("#properties")
        tc.find("In order to edit this ticket you need to be either")

        second_ticket_id = self._tester.create_new_agilo_task('my task')
        self._assert_no_brute_force_ticket_change(second_ticket_id, ticket_id)
コード例 #29
0
ファイル: admin.py プロジェクト: pkdevbox/trac
 def runTest(self):
     """Admin remove priority"""
     name = "RemovePriority"
     self._tester.create_priority(name)
     priority_url = self._tester.url + '/admin/ticket/priority'
     tc.go(priority_url)
     tc.url(priority_url + '$')
     tc.find(name)
     tc.formvalue('enumtable', 'sel', name)
     tc.submit('remove')
     tc.url(priority_url + '$')
     tc.notfind(name)
コード例 #30
0
    def runTest(self):
        # Create a requirement as a Product Owner, than test that a Team Member
        # can't edit it
        self._tester.login_as(Usernames.product_owner)
        ticket_id = self._tester.create_new_agilo_ticket(Type.REQUIREMENT, 'req')
        self._tester.login_as(Usernames.team_member)
        self._tester.go_to_view_ticket_page(ticket_id, should_fail=True)
        tc.notfind("#properties")
        tc.find("In order to edit this ticket you need to be either")

        # Now try to create a ticket as well
        ticket_id = self._tester.create_new_agilo_ticket(Type.REQUIREMENT, 'req', should_fail=True)
コード例 #31
0
ファイル: backlog_admin_test.py プロジェクト: nagyist/agilo
 def _test_backlog_deletion(self, backlog_name):
     # test deletion
     tc.formvalue('backlog_table', 'sel', '+' + backlog_name)
     tc.submit('remove')
     tc.notfind(backlog_name)
コード例 #32
0
 def runTest(self):
     story_id = self.ids[1]
     self.tester.go_to_product_backlog()
     tc.notfind("id=\"ticketID-%s\"" % story_id)
コード例 #33
0
ファイル: functional.py プロジェクト: minimalistduck/trac
    def runTest(self):
        """Test for simple wiki rename"""
        pagename = self._tester.create_wiki_page()
        attachment = self._tester.attach_file_to_wiki(pagename)
        base_url = self._tester.url
        page_url = base_url + "/wiki/" + pagename

        def click_rename():
            tc.formvalue('rename', 'action', 'rename')
            tc.submit()
            tc.url(page_url + r'\?action=rename')
            tc.find("New name:")

        tc.go(page_url)
        tc.find("Rename page")
        click_rename()
        # attempt to give an empty new name
        tc.formvalue('rename-form', 'new_name', '')
        tc.submit('submit')
        tc.url(page_url)
        tc.find("A new name is mandatory for a rename")
        # attempt to rename the page to an invalid page name
        tc.formvalue('rename-form', 'new_name', '../WikiStart')
        tc.submit('submit')
        tc.url(page_url)
        tc.find("The new name is invalid")
        # attempt to rename the page to the current page name
        tc.formvalue('rename-form', 'new_name', pagename)
        tc.submit('submit')
        tc.url(page_url)
        tc.find("The new name must be different from the old name")
        # attempt to rename the page to an existing page name
        tc.formvalue('rename-form', 'new_name', 'WikiStart')
        tc.submit('submit')
        tc.url(page_url)
        tc.find("The page WikiStart already exists")
        # correct rename to new page name (old page replaced by a redirection)
        tc.go(page_url)
        click_rename()
        newpagename = pagename + 'Renamed'
        tc.formvalue('rename-form', 'new_name', newpagename)
        tc.formvalue('rename-form', 'redirect', True)
        tc.submit('submit')
        # check redirection page
        tc.url(page_url)
        tc.find("See.*/wiki/" + newpagename)
        tc.find("The page %s has been renamed to %s." %
                (pagename, newpagename))
        tc.find("The page %s has been recreated with a redirect to %s." %
                (pagename, newpagename))
        # check whether attachment exists on the new page but not on old page
        tc.go(base_url + '/attachment/wiki/' + newpagename + '/' + attachment)
        tc.notfind("Error: Invalid Attachment")
        tc.go(base_url + '/attachment/wiki/' + pagename + '/' + attachment)
        tc.find("Error: Invalid Attachment")
        # rename again to another new page name (this time, no redirection)
        tc.go(page_url)
        click_rename()
        newpagename = pagename + 'RenamedAgain'
        tc.formvalue('rename-form', 'new_name', newpagename)
        tc.formvalue('rename-form', 'redirect', False)
        tc.submit('submit')
        tc.url(base_url + "/wiki/" + newpagename)
        tc.find("The page %s has been renamed to %s." %
                (pagename, newpagename))
        # this time, the original page is gone
        tc.go(page_url)
        tc.url(page_url)
        tc.find("The page[ \n]+%s[ \n]+does not exist" % tag.strong(pagename))
コード例 #34
0
    def test_set_owner(self):
        """When using the workflow operation `set_owner` with
        a specific list of available owners, the assign-to field
        will only contain that list of owners.  The requesting user
        will not be added to the list, and the current ticket owner
        will not be added to the list.
        """
        try:
            ticket_id = self._tester.create_ticket(self.__class__.__name__,
                                                   info={'owner': 'lammy'})
            self.env.config.set('ticket-workflow', 'reassign.set_owner',
                                "alice,bill")
            self.env.config.save()

            self._tester.go_to_ticket(ticket_id)
            tc.find('The owner will be changed from '
                    '<span class="trac-author">lammy</span>')

            tc.notfind(
                '<input type="text" name="action_reassign_reassign_owner" '
                'value="admin" id="action_reassign_reassign_owner" />')
            tc.notfind(
                '<option selected="selected" value="admin">admin</option>')
            tc.notfind('<option value="admin">admin</option>')

            tc.notfind(
                '<input type="text" name="action_reassign_reassign_owner" '
                'value="lammy" id="action_reassign_reassign_owner" />')
            tc.notfind(
                '<option selected="selected" value="lammy">lammy</option>')
            tc.notfind('<option value="lammy">lammy</option>')

        finally:
            self.env.config.remove('ticket-workflow', 'reassign.set_owner')
コード例 #35
0
    def test_set_owner_one_choice(self):
        """When using the workflow operation `set_owner` with
        a specific single-element list of available owners, the assign-to field
        will not give the end user any choices at all.
        """
        try:
            ticket_id = self._tester.create_ticket(self.__class__.__name__,
                                                   info={'owner': 'lammy'})
            self.env.config.set('ticket-workflow', 'reassign.set_owner',
                                "alice")
            self.env.config.save()

            self._tester.go_to_ticket(ticket_id)

            tc.notfind('<select name="action_reassign_reassign_owner"')
            tc.find('<input id="action_reassign_reassign_owner" '
                    'name="action_reassign_reassign_owner" type="hidden" '
                    'value="alice" />')
            tc.find('The owner will be changed from '
                    '<span class="trac-author">lammy</span> to '
                    '<span class="trac-author">alice</span>')

            tc.notfind('<input id="action_reassign_reassign_owner" '
                       'name="action_reassign_reassign_owner" type="text" '
                       'value="admin" />')
            tc.notfind(
                '<option selected="selected" value="admin">admin</option>')
            tc.notfind('<option value="admin">admin</option>')

            tc.notfind('<input id="action_reassign_reassign_owner"'
                       'name="action_reassign_reassign_owner" type="text" '
                       'value="lammy" />')
            tc.notfind(
                '<option selected="selected" value="lammy">lammy</option>')
            tc.notfind('<option value="lammy">lammy</option>')

        finally:
            self.env.config.remove('ticket-workflow', 'reassign.set_owner')
コード例 #36
0
ファイル: functional.py プロジェクト: zxfly/trac
    def runTest(self):
        """Tests for the Copy Permissions functionality
        added in http://trac.edgewall.org/ticket/11099."""
        checkbox_value = lambda s, p: '%s:%s' % (unicode_to_base64(s),
                                                 unicode_to_base64(p))
        grant_msg = "The subject %s has been granted the permission %s\."

        def grant_permission(subject, action):
            tc.formvalue('addperm', 'gp_subject', subject)
            tc.formvalue('addperm', 'action', action)
            tc.submit()
            tc.find(grant_msg % (subject, action))
            tc.find(checkbox_value(subject, action))

        env = self._testenv.get_trac_environment()

        # Copy permissions from subject to target
        self._tester.go_to_admin('Permissions')
        perm_sys = PermissionSystem(env)
        anon_perms = perm_sys.store.get_user_permissions('anonymous')
        for perm in anon_perms:
            tc.find(checkbox_value('anonymous', perm))
            tc.notfind(checkbox_value('user1', perm))
        tc.formvalue('copyperm', 'cp_subject', 'anonymous')
        tc.formvalue('copyperm', 'cp_target', 'user1')
        tc.submit()
        for perm in anon_perms:
            tc.find("The subject user1 has been granted the permission %s\." %
                    perm)
            tc.find(checkbox_value('user1', perm))

        # Subject doesn't have any permissions
        tc.notfind(checkbox_value('noperms', ''))
        tc.formvalue('copyperm', 'cp_subject', 'noperms')
        tc.formvalue('copyperm', 'cp_target', 'user1')
        tc.submit()
        tc.find("The subject noperms does not have any permissions\.")

        # Subject belongs to group but doesn't directly have any permissions
        grant_permission('group1', 'TICKET_VIEW')
        tc.formvalue('addsubj', 'sg_subject', 'noperms')
        tc.formvalue('addsubj', 'sg_group', 'group1')
        tc.submit()
        tc.find("The subject noperms has been added to the group group1\.")

        tc.formvalue('copyperm', 'cp_subject', 'noperms')
        tc.formvalue('copyperm', 'cp_target', 'user1')
        tc.submit()
        tc.find("The subject noperms does not have any permissions\.")

        # Target uses reserved all upper-case form
        tc.formvalue('copyperm', 'cp_subject', 'noperms')
        tc.formvalue('copyperm', 'cp_target', 'USER1')
        tc.submit()
        tc.find("All upper-cased tokens are reserved for permission names\.")
        self._tester.go_to_admin("Permissions")

        # Subject users reserved all upper-case form
        tc.formvalue('copyperm', 'cp_subject', 'USER1')
        tc.formvalue('copyperm', 'cp_target', 'noperms')
        tc.submit()
        tc.find("All upper-cased tokens are reserved for permission names\.")
        self._tester.go_to_admin("Permissions")

        # Target already possess one of the permissions
        anon_perms = perm_sys.store.get_user_permissions('anonymous')
        for perm in anon_perms:
            tc.notfind(checkbox_value('user2', perm))
        grant_permission('user2', anon_perms[0])

        tc.formvalue('copyperm', 'cp_subject', 'anonymous')
        tc.formvalue('copyperm', 'cp_target', 'user2')
        tc.submit()

        tc.notfind("The subject <em>user2</em> has been granted the "
                   "permission %s\." % anon_perms[0])
        for perm in anon_perms[1:]:
            tc.find("The subject user2 has been granted the permission %s\." %
                    perm)
            tc.find(checkbox_value('user2', perm))

        # Subject has a permission that is no longer defined
        try:
            env.db_transaction("INSERT INTO permission VALUES (%s,%s)",
                               ('anonymous', 'NOTDEFINED_PERMISSION'))
        except env.db_exc.IntegrityError:
            pass
        env.config.touch()  # invalidate permission cache
        tc.reload()
        tc.find(checkbox_value('anonymous', 'NOTDEFINED_PERMISSION'))
        perm_sys = PermissionSystem(env)
        anon_perms = perm_sys.store.get_user_permissions('anonymous')
        for perm in anon_perms:
            tc.notfind(checkbox_value('user3', perm))

        tc.formvalue('copyperm', 'cp_subject', 'anonymous')
        tc.formvalue('copyperm', 'cp_target', 'user3')
        tc.submit()

        for perm in anon_perms:
            msg = grant_msg % ('user3', perm)
            if perm == 'NOTDEFINED_PERMISSION':
                tc.notfind(msg)
                tc.notfind(checkbox_value('user3', perm))
            else:
                tc.find(msg)
                tc.find(checkbox_value('user3', perm))
        perm_sys.revoke_permission('anonymous', 'NOTDEFINED_PERMISSION')

        # Actor doesn't posses permission
        grant_permission('anonymous', 'PERMISSION_GRANT')
        grant_permission('user3', 'TRAC_ADMIN')
        self._tester.logout()
        self._tester.go_to_admin("Permissions")

        try:
            tc.formvalue('copyperm', 'cp_subject', 'user3')
            tc.formvalue('copyperm', 'cp_target', 'user4')
            tc.submit()

            perm_sys = PermissionSystem(env)
            for perm in [
                    perm[1] for perm in perm_sys.get_all_permissions()
                    if perm[0] == 'user3' and perm[1] != 'TRAC_ADMIN'
            ]:
                tc.find(grant_msg % ('user4', perm))
            tc.notfind("The permission TRAC_ADMIN was not granted to user4 "
                       "because users cannot grant permissions they don't "
                       "possess.")
        finally:
            self._testenv.revoke_perm('anonymous', 'PERMISSION_GRANT')
            self._tester.login('admin')
コード例 #37
0
    def runTest(self):
        env = self._testenv.get_trac_environment()
        create_file(
            os.path.join(env.plugins_dir, 'RaiseExceptionPlugin.py'), """\
from trac.core import Component, TracError, implements
from trac.web.api import IRequestHandler
from trac.util.html import html

url = None

class RaiseExceptionPlugin(Component):
    implements(IRequestHandler)

    def match_request(self, req):
        if req.path_info.startswith('/raise-exception'):
            return True

    def process_request(self, req):
        if req.args.get('type') == 'tracerror':
            if req.args.get('div'):
                raise TracError(html.div("The message in a div",
                                class_='message'))
            elif req.args.get('p'):
                raise TracError(html.p("The message in a p",
                                class_='message'))
            elif req.args.get('i'):
                raise TracError(html("The message with ",
                                     html.span("inline span"),
                                     " element"))
            else:
                raise TracError("The plaintext message")
        else:
            if req.args.get('report') == 'tho':
                global url
                url = 'http://trac-hacks.org/wiki/HelloWorldMacro'
            raise Exception

""")
        self._testenv.restart()

        try:
            tc.go(self._tester.url + '/raise-exception')
            tc.find(internal_error)
            tc.find('<form class="newticket" method="get" '
                    'action="https://trac.edgewall.org/newticket">')

            tc.go(self._tester.url + '/raise-exception?report=tho')
            tc.find(internal_error)
            tc.find('<form class="newticket" method="get" '
                    'action="http://trac-hacks.org/newticket">')
            tc.find('<input type="hidden" name="component" '
                    'value="HelloWorldMacro" />')

            tc.go(self._tester.url +
                  '/raise-exception?type=tracerror&div=true')
            tc.notfind(internal_error)
            tc.find('<h1>Trac Error</h1>[ \t\n]+'
                    '<div class="message">The message in a div</div>')

            tc.go(self._tester.url + '/raise-exception?type=tracerror&p=true')
            tc.notfind(internal_error)
            tc.find('<h1>Trac Error</h1>[ \t\n]+'
                    '<p class="message">The message in a p</p>')

            tc.go(self._tester.url + '/raise-exception?type=tracerror&i=true')
            tc.notfind(internal_error)
            tc.find('<h1>Trac Error</h1>[ \t\n]+'
                    '<p class="message">The message with '
                    '<span>inline span</span> element</p>')

            tc.go(self._tester.url + '/raise-exception?type=tracerror')
            tc.find('<h1>Trac Error</h1>[ \t\n]+'
                    '<p class="message">The plaintext message</p>')
        finally:
            env.config.set('components', 'RaiseExceptionPlugin.*', 'disabled')
コード例 #38
0
 def runTest(self):
     """Test for regression of the fix in r5785"""
     self._tester.go_to_preferences()
     tc.submit('logout', 'logout')
     tc.notfind(internal_error)  # See [5785]
     tc.follow('Login')
コード例 #39
0
ファイル: functional.py プロジェクト: minimalistduck/trac
 def runTest(self):
     """Test for regression of http://trac.edgewall.org/ticket/4812"""
     pagename = random_unique_camel() + '/' + random_unique_camel()
     self._tester.create_wiki_page(pagename)
     self._tester.attach_file_to_wiki(pagename)
     tc.notfind('does not exist')
コード例 #40
0
    def runTest(self):
        self._tester.login_as(Usernames.admin)
        page_url = self._tester.url + '/admin/agilo/teams'
        #TODO: find a way to test with umlaut without compromising the encoding
        team_name = self.classname() + 'Team'
        utf8_team_name = team_name.encode('UTF-8')
        team_desc = "'''Testdescription'''"
        self._tester.create_new_team(team_name)

        # set description
        tc.fv('modcomp', 'description', team_desc)
        tc.submit('save')

        # back at list view
        tc.url(page_url)
        tc.code(200)

        # add a new team and team member
        #TODO: find a way to test team names with umlaut without assuming the
        # locale of the testing system is UTF-8.de_DE
        member_name = self.classname() + 'Member'
        utf8_member_name = member_name.encode('UTF-8')
        member_desc = "Goldmember"

        team_name2 = "T-team"
        tc.fv('addteam', 'name', team_name2)
        tc.submit('add')
        tc.code(200)

        tc.fv('modcomp', 'team_member', utf8_member_name)
        tc.fv('modcomp', 'member_description', member_desc)
        tc.submit('add')
        tc.code(200)

        try:
            # IF the accountmanagerplugin is enabled has to appear
            #       the Confirm user creation frame
            tc.find('Create new user')
        except TwillAssertionError:
            account_manager_plugin_enabled = False
        else:
            account_manager_plugin_enabled = True
            tc.fv('modcomp', 'createUser_ok', 'click')
            tc.submit('createUser_ok')
            tc.code(200)

        # correct team selected?
        tc.find('<option selected="selected">%s</option>' % team_name2)
        tc.find(utf8_member_name)
        tc.find(member_desc)

        # set new value for mondays and tuesdays
        tc.fv('modcomp', 'ts_0', '0')
        tc.fv('modcomp', 'ts_1', '')
        tc.submit('save')

        # back at team page
        tc.url("%s/%s" % (page_url, quote(team_name2)))
        tc.find(utf8_member_name)
        # three days x 6h
        tc.find('18.0h')

        user_not_confirmed = None
        if account_manager_plugin_enabled:
            # start to add a new user as team member but cancel at last
            user_not_confirmed = 'user-not-confirmed'
            tc.fv('modcomp', 'team_member', user_not_confirmed)
            tc.submit('add')
            # abort user creation
            tc.find('Create new user')
            tc.fv('modcomp', 'createUser_cancel', 'click')
            tc.submit('createUser_cancel')

        # back at team page
        tc.url("%s/%s" % (page_url, quote(team_name2)))
        tc.find(utf8_member_name)
        if user_not_confirmed is not None:
            tc.notfind(user_not_confirmed)

        # change team
        tc.follow(utf8_member_name)
        tc.fv('modcomp', 'team', utf8_team_name)
        tc.submit('save')
        tc.notfind(utf8_member_name)
        tc.go("%s/%s" % (page_url, unicode_quote(team_name)))
        tc.find(utf8_member_name)

        # --------- unassigned team members functionality --------
        # add another team member to team 1
        member_name2 = 'member #2'
        tc.fv('modcomp', 'team_member', member_name2)
        tc.submit('add')

        if account_manager_plugin_enabled:
            tc.find('Create new user')
            tc.find(member_name2)
            tc.fv('modcomp', 'createUser_ok', 'click')
            tc.submit('createUser_ok')

        tc.fv('modcomp', 'member_description', '')
        tc.submit('save')

        # back at team list, delete first team member
        tc.url("%s/%s" % (page_url, unicode_quote(team_name)))
        tc.fv('modcomp', 'delete', utf8_member_name)
        tc.submit('save')
        # same url, should not list this member anymore
        tc.url("%s/%s" % (page_url, unicode_quote(team_name)))
        tc.notfind(utf8_member_name)

        # select the other one but cancel back to team list. Formvalue
        # must use True here because Twill treats checkboxes differently
        # when there are several with the same name or only one
        tc.fv('modcomp', 'delete', True)
        tc.submit('cancel')
        tc.go(page_url)
        tc.follow('Unassigned team members')

        # shows the member we deleted, not the one we canceled on
        tc.url(page_url + "/unassigned")
        tc.find(utf8_member_name)
        tc.notfind(member_name2)

        # completely delete the team member
        tc.fv('modcomp', 'delete', True)
        tc.submit('remove')

        # no team members without teams anymore
        tc.url(page_url)
        tc.notfind('unassigned')

        # now delete the teams
        tc.fv('team_table', 'delete', utf8_team_name)
        tc.fv('team_table', 'delete', team_name2)
        tc.submit()

        tc.notfind(utf8_team_name)
        tc.notfind(team_name2)
        tc.find('unassigned')
コード例 #41
0
ファイル: ticket_gui_test.py プロジェクト: nagyist/agilo
 def runTest(self):
     self._tester.go_to_front()
     tc.notfind('New Ticket')
コード例 #42
0
ファイル: functional.py プロジェクト: minimalistduck/trac
    def runTest(self):
        """Test for regression of http://trac.edgewall.org/ticket/10957"""

        self._tester.go_to_front()
        try:
            self._tester.logout()

            # Check that page can't be created without WIKI_CREATE
            page_name = random_unique_camel()
            self._tester.go_to_wiki(page_name)
            tc.find("Trac Error")
            tc.find("Page %s not found" % page_name)
            tc.notfind("Create this page")
            tc.go(self._tester.url + '/wiki/%s?action=edit' % page_name)
            tc.find("Error: Forbidden")
            tc.find(
                "WIKI_CREATE privileges are required to perform this "
                "operation on %s. You don&#39;t have the required permissions."
                % page_name)

            # Check that page can be created when user has WIKI_CREATE
            self._testenv.grant_perm('anonymous', 'WIKI_CREATE')
            content_v1 = random_sentence()
            self._tester.create_wiki_page(page_name, content_v1)
            tc.find(content_v1)

            # Check that page can't be edited without WIKI_MODIFY
            tc.notfind("Edit this page")
            tc.notfind("Attach file")
            tc.go(self._tester.url + '/wiki/%s?action=edit' % page_name)
            tc.find("Error: Forbidden")
            tc.find(
                "WIKI_MODIFY privileges are required to perform this "
                "operation on %s. You don&#39;t have the required permissions."
                % page_name)

            # Check that page can be edited when user has WIKI_MODIFY
            self._testenv.grant_perm('anonymous', 'WIKI_MODIFY')
            self._tester.go_to_wiki(page_name)
            tc.find("Edit this page")
            tc.find("Attach file")
            content_v2 = random_sentence()
            self._tester.edit_wiki_page(page_name, content_v2)
            tc.find(content_v2)

            # Check that page can be reverted to a previous revision
            tc.go(self._tester.url + '/wiki/%s?version=1' % page_name)
            tc.find("Revert to this version")
            tc.formvalue('modifypage', 'action', 'edit')
            tc.submit()
            tc.find(content_v1)

            # Check that page can't be reverted without WIKI_MODIFY
            self._tester.edit_wiki_page(page_name)
            self._testenv.revoke_perm('anonymous', 'WIKI_MODIFY')
            tc.go(self._tester.url + '/wiki/%s?version=1' % page_name)
            tc.notfind("Revert to this version")
            tc.go(self._tester.url +
                  '/wiki/%s?action=edit&version=1' % page_name)
            tc.find(
                "WIKI_MODIFY privileges are required to perform this "
                "operation on %s. You don&#39;t have the required permissions."
                % page_name)

        finally:
            # Restore pre-test state.
            self._tester.login('admin')
            self._testenv.revoke_perm('anonymous', 'WIKI_CREATE')
コード例 #43
0
ファイル: functional.py プロジェクト: minimalistduck/trac
 def runTest(self):
     """Test for regression of http://trac.edgewall.org/ticket/8976
     Test fine grained permissions policy on wiki for specific page
     versions."""
     name = self._tester.create_wiki_page()
     self._tester.edit_wiki_page(name)
     self._tester.edit_wiki_page(name)
     self._tester.logout()
     self._tester.login('user')
     try:
         self._tester.go_to_wiki(name, 1)
         tc.notfind(r"\bError: Forbidden\b")
         self._tester.go_to_wiki(name, 2)
         tc.notfind(r"\bError: Forbidden\b")
         self._tester.go_to_wiki(name, 3)
         tc.notfind(r"\bError: Forbidden\b")
         self._tester.go_to_wiki(name, 4)
         tc.find(r"\bTrac Error\b")
         self._tester.go_to_wiki(name)
         tc.notfind(r"\bError: Forbidden\b")
         self._testenv.enable_authz_permpolicy("""
             [wiki:%(name)s@1]
             * = !WIKI_VIEW
             [wiki:%(name)s@2]
             * = WIKI_VIEW
             [wiki:%(name)s@3]
             * = !WIKI_VIEW
             [wiki:%(name)s]
             * = WIKI_VIEW
         """ % {'name': name})
         self._tester.go_to_wiki(name, 1)
         tc.find(r"\bError: Forbidden\b")
         self._tester.go_to_wiki(name, 2)
         tc.notfind(r"\bError: Forbidden\b")
         self._tester.go_to_wiki(name, 3)
         tc.find(r"\bError: Forbidden\b")
         self._tester.go_to_wiki(name, 4)
         tc.find(r"\bTrac Error\b")
         self._tester.go_to_wiki(name)
         tc.notfind(r"\bError: Forbidden\b")
         self._tester.edit_wiki_page(name)
     finally:
         self._tester.logout()
         self._tester.login('admin')
         self._testenv.disable_authz_permpolicy()
コード例 #44
0
 def _assert_task_is_not_linked_to_bug(self, target_id, source_id):
     self._tester.go_to_view_ticket_page(target_id)
     tc.notfind('#%d</a>' % source_id)
     
     self._tester.go_to_view_ticket_page(source_id)
     tc.notfind('#%d</a>' % target_id)
コード例 #45
0
ファイル: functional.py プロジェクト: starworldx/trac
 def runTest(self):
     """Test for regression of the source browser fix in r5877"""
     tc.go(self._tester.url + '/browser?range_min_secs=1')
     tc.notfind(internal_error)
コード例 #46
0
    def runTest(self):
        """Test for regression of http://trac.edgewall.org/ticket/11337
        The language select will be disabled if Babel is not installed and a
        hint will be shown. The text of the hint is dependent on whether the
        user has TRAC_ADMIN and the message catalogs have been compiled.
        """
        from trac.util.translation import has_babel, get_available_locales

        babel_hint = "Install Babel for extended language support."
        catalog_hint = "Message catalogs have not been compiled."
        nonadmin_hint = r"Please contact your\s+Trac administrator\s+" \
                        r"to enable existing translations."
        language_select = '<select id="language" name="language">'
        disabled_language_select = \
            '<select id="language" name="language" disabled="disabled" ' \
            'title="Translations are currently unavailable">'

        self._tester.go_to_preferences("Localization")
        if has_babel:
            tc.notfind(babel_hint)
            if get_available_locales():
                tc.find(language_select)
                tc.notfind(babel_hint)
                tc.notfind(catalog_hint)
            else:
                tc.find(disabled_language_select)
                tc.find(catalog_hint)
                tc.notfind(babel_hint)
        else:
            tc.find(disabled_language_select)
            tc.find(babel_hint)
            tc.notfind(catalog_hint)
        tc.notfind(nonadmin_hint)

        # For users without TRAC_ADMIN, the Language tab should only be
        # present when Babel is installed
        self._tester.logout()
        self._tester.go_to_preferences("Localization")
        try:
            if has_babel and get_available_locales():
                tc.find(language_select)
                tc.notfind(nonadmin_hint)
            elif has_babel:
                tc.find(disabled_language_select)
                tc.find(nonadmin_hint)
            else:
                tc.find(disabled_language_select)
                tc.find(nonadmin_hint)
            tc.notfind(catalog_hint)
            tc.notfind(babel_hint)
        finally:
            self._tester.login('admin')
コード例 #47
0
ファイル: admin.py プロジェクト: jacdevos/trac
    def runTest(self):
        """Admin set default ticket milestone, default retarget milestone
        and clear defaults."""
        def clear_defaults():
            # Test the "Clear default" button
            tc.go(milestone_url)
            tc.submit('clear', formname='milestone_table')
            tc.notfind('type="radio" name="ticket_default" '
                       'checked="checked" value=".+"')
            tc.notfind('type="radio" name="retarget_default" '
                       'checked="checked value=".+""')
            self._tester.go_to_ticket(tid)
            tc.find('<th class="missing" id="h_milestone">[ \t\n]+'
                    'Milestone:[ \t\n]+</th>[ \t\n]+'
                    '(?!<td headers="h_milestone">)')
            self._tester.go_to_milestone(mid2)
            tc.submit(formname='deletemilestone')
            tc.notfind('<option selected="selected" value="%s">%s</option>' %
                       (mid1, mid1))

        milestone_url = self._tester.url + "/admin/ticket/milestones"
        tid = self._tester.create_ticket()
        mid1 = self._tester.create_milestone()
        mid2 = self._tester.create_milestone()
        self._tester.create_ticket(info={'milestone': mid2})

        # Set default ticket milestone
        tc.go(milestone_url)
        tc.formvalue('milestone_table', 'ticket_default', mid1)
        tc.submit('apply')
        tc.find('type="radio" name="ticket_default"'
                ' checked="checked" value="%s"' % mid1)
        tc.notfind('type="radio" name="retarget_default"'
                   ' checked="checked" value=".+"')
        # verify it is the default on the newticket page.
        tc.go(self._tester.url + '/newticket')
        tc.find('<option selected="selected" value="%s">%s</option>' %
                (mid1, mid1))
        clear_defaults()

        # Set default retarget to milestone
        tc.go(milestone_url)
        tc.formvalue('milestone_table', 'retarget_default', mid1)
        tc.submit('apply')
        tc.find('type="radio" name="retarget_default"'
                ' checked="checked" value="%s"' % mid1)
        tc.notfind('type="radio" name="ticket_default"'
                   ' checked="checked" value=".+"')
        # verify it is the default on the confirm delete page.
        self._tester.go_to_milestone(mid2)
        tc.submit(formname='deletemilestone')
        tc.find('<option selected="selected" value="%s">%s</option>' %
                (mid1, mid1))
        clear_defaults()

        # Set both
        tc.go(milestone_url)
        tc.formvalue('milestone_table', 'ticket_default', mid1)
        tc.formvalue('milestone_table', 'retarget_default', mid1)
        tc.submit('apply')
        tc.find('type="radio" name="ticket_default"'
                ' checked="checked" value="%s"' % mid1)
        tc.find('type="radio" name="retarget_default"'
                ' checked="checked" value="%s"' % mid1)
        # verify it is the default on the newticket page.
        tc.go(self._tester.url + '/newticket')
        tc.find('<option selected="selected" value="%s">%s</option>' %
                (mid1, mid1))
        # verify it is the default on the confirm delete page.
        self._tester.go_to_milestone(mid2)
        tc.submit(formname='deletemilestone')
        tc.find('<option selected="selected" value="%s">%s</option>' %
                (mid1, mid1))
        clear_defaults()

        #Set neither
        tc.go(milestone_url)
        tc.submit('apply', formname='milestone_table')
        tc.notfind('type="radio" name="retarget_default"'
                   ' checked="checked" value=".+"')
        tc.notfind('type="radio" name="ticket_default"'
                   ' checked="checked" value=".+"')
        # verify no default on the newticket page.
        tc.go(self._tester.url + '/newticket')
        tc.find('<th class="missing" id="h_milestone">[ \t\n]+'
                'Milestone:[ \t\n]+</th>[ \t\n]+'
                '(?!<td headers="h_milestone">)')
        # verify none selected on the confirm delete page.
        self._tester.go_to_milestone(mid2)
        tc.submit(formname='deletemilestone')
        tc.notfind('<option selected="selected" value="%s">%s</option>' %
                   (mid1, mid1))