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')
def runTest(self): """Test for regression of http://trac.edgewall.org/ticket/11515 Show a notice message with new language setting after it is changed. """ from trac.util.translation import has_babel, get_available_locales from pkg_resources import resource_exists, resource_filename if not has_babel: return if not resource_exists("trac", "locale"): return locale_dir = resource_filename("trac", "locale") from babel.support import Translations string = "Your preferences have been saved." translated = None for second_locale in get_available_locales(): tx = Translations.load(locale_dir, second_locale) translated = tx.dgettext("messages", string) if string != translated: break # the locale has a translation else: return try: self._tester.go_to_preferences("Language") tc.formvalue("userprefs", "language", second_locale) tc.submit() tc.find(re.escape(translated)) finally: tc.formvalue("userprefs", "language", "") # revert to default tc.submit() tc.find("Your preferences have been saved")
def runTest(self): self.tester.login_as(Usernames.product_owner) requirement_id = self.tester.create_new_agilo_requirement('My Requirement') self.tester.go_to_view_ticket_page(requirement_id) self.tester.select_form_for_twill('attachfile', 'attachfilebutton') tc.submit('attachfile') tc.find('Add Attachment to')
def runTest(self): """Edit a wiki page.""" pagename = self._tester.create_wiki_page() self._tester.edit_wiki_page(pagename) tc.find("Your changes have been saved in version 2") tc.find(r'\(<a href="/wiki/%s\?action=diff&version=2">diff</a>\)' % pagename)
def runTest(self): """Test for regression of http://trac.edgewall.org/ticket/11194 TracError should be raised when repository with name already exists """ self._tester.go_to_admin() tc.follow("\\bRepositories\\b") tc.url(self._tester.url + "/admin/versioncontrol/repository") word = random_word() names = ["%s_%d" % (word, n) for n in xrange(3)] tc.formvalue("trac-addrepos", "name", names[0]) tc.formvalue("trac-addrepos", "dir", "/var/svn/%s" % names[0]) tc.submit() tc.notfind(internal_error) tc.formvalue("trac-addrepos", "name", names[1]) tc.formvalue("trac-addrepos", "dir", "/var/svn/%s" % names[1]) tc.submit() tc.notfind(internal_error) tc.follow("\\b" + names[1] + "\\b") tc.url(self._tester.url + "/admin/versioncontrol/repository/" + names[1]) tc.formvalue("edit", "name", names[2]) tc.submit("save") tc.notfind(internal_error) tc.url(self._tester.url + "/admin/versioncontrol/repository") tc.follow("\\b" + names[2] + "\\b") tc.url(self._tester.url + "/admin/versioncontrol/repository/" + names[2]) tc.formvalue("edit", "name", names[0]) tc.submit("save") tc.find('The repository "%s" already exists.' % names[0]) tc.notfind(internal_error)
def runTest(self): """Test for regression of http://trac.edgewall.org/ticket/11194 TracError should be raised when repository with name already exists """ self._tester.go_to_admin() tc.follow("\\bRepositories\\b") tc.url(self._tester.url + '/admin/versioncontrol/repository') word = random_word() names = ['%s_%d' % (word, n) for n in xrange(3)] tc.formvalue('trac-addrepos', 'name', names[0]) tc.formvalue('trac-addrepos', 'dir', '/var/svn/%s' % names[0]) tc.submit() tc.notfind(internal_error) tc.formvalue('trac-addrepos', 'name', names[1]) tc.formvalue('trac-addrepos', 'dir', '/var/svn/%s' % names[1]) tc.submit() tc.notfind(internal_error) tc.follow('\\b' + names[1] + '\\b') tc.url(self._tester.url + '/admin/versioncontrol/repository/' + names[1]) tc.formvalue('trac-modrepos', 'name', names[2]) tc.submit('save') tc.notfind(internal_error) tc.url(self._tester.url + '/admin/versioncontrol/repository') tc.follow('\\b' + names[2] + '\\b') tc.url(self._tester.url + '/admin/versioncontrol/repository/' + names[2]) tc.formvalue('trac-modrepos', 'name', names[0]) tc.submit('save') tc.find('The repository "%s" already exists.' % names[0]) tc.notfind(internal_error)
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')
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 type="hidden" ' 'name="action_reassign_reassign_owner" ' 'value="alice" id="action_reassign_reassign_owner" />') tc.find('The owner will be changed from ' '<span class="trac-author">lammy</span> to ' '<span class="trac-author">alice</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')
def runTest(self): """Set preferences for syntax highlighting.""" self._tester.go_to_preferences("Syntax Highlighting") tc.find('<option value="trac" selected="selected">') tc.formvalue('userprefs', 'style', 'Emacs') tc.submit() tc.find('<option value="emacs" selected="selected">')
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')
def runTest(self): """Test for regression of http://trac.edgewall.org/ticket/11302""" pagename = self._tester.create_wiki_page() self._tester.attach_file_to_wiki( pagename, description="illustrates [./@1#point1]") self._tester.go_to_wiki(pagename + '?action=edit') tc.find(r'illustrates <a class="wiki"' r' href="/wiki/%s\?version=1#point1">@1</a>' % pagename)
def runTest(self): """Admin milestone duedate""" name = "DueMilestone" duedate = datetime.now(tz=utc) duedate_string = format_datetime(duedate, tzinfo=utc, locale=locale_en) self._tester.create_milestone(name, due=duedate_string) tc.find(duedate_string)
def runTest(self): self._tester.login_as(Usernames.product_owner) ticket_id = self._tester.create_new_agilo_ticket(Type.REQUIREMENT, 'req') self._tester.go_to_view_ticket_page(ticket_id) new_summary = 'really interesting' tc.formvalue('propertyform', 'field_summary', new_summary) tc.submit('submit') tc.find(new_summary)
def runTest(self): """Verify browser log for a new file""" tempfilename = random_word() + '_new.txt' fulltempfilename = 'component1/trunk/' + tempfilename revision = self._testenv.svn_add(fulltempfilename, '') tc.go(self._tester.url + '/log/' + fulltempfilename) tc.find('@%d' % revision) tc.find('Add %s' % fulltempfilename)
def runTest(self): """Verify browser log for a new file""" tempfilename = random_word() + "_new.txt" fulltempfilename = "component1/trunk/" + tempfilename revision = self._testenv.svn_add(fulltempfilename, "") tc.go(self._tester.url + "/log/" + fulltempfilename) tc.find("@%d" % revision) tc.find("Add %s" % fulltempfilename)
def runTest(self): """Turn off logging.""" # For now, we just check that it shows up. self._tester.go_to_admin("Logging") tc.find('trac.log') tc.formvalue('modlog', 'log_type', 'none') tc.submit() tc.find('selected="selected">None</option')
def runTest(self): self._tester.login_as(Usernames.product_owner) 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_update_import(csv_delete_data) tc.find('<h1>Update Preview</h1>') tc.find('File contents read with encoding <b>%s</b>.' % encoding)
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)
def _test_ajax_update_fields(self): # test Ajax functionality by clicking "update fields" or # passing the new values as a GET parameter tc.fv('modcomp', 'scope', 'milestone') tc.submit('preview') # see if the available and selected fields for this backlog # type are display correctly tc.find('<option selected="selected" [^>]*>milestone</option>')
def runTest(self): self._tester.login_as(Usernames.team_member) page_url = self._tester.url + TEAM_URL tc.go(page_url) tc.url(page_url) tc.code(200) tc.follow('Team#1') tc.code(200) tc.find('Member#1')
def runTest(self): """Repository with an invalid path is rendered with an error message on the repository admin page. """ self._tester.go_to_admin("Repositories") tc.formvalue("trac-addrepos", "name", "InvalidRepos") tc.formvalue("trac-addrepos", "dir", "/the/invalid/path") tc.submit() tc.find((u'<span class="missing" title="[^"]*">' u"/the/\u200binvalid/\u200bpath</span>").encode("utf-8"))
def _assert_comment_not_saved(self, ticket_id, comment): self._go_to_comment_form(ticket_id) try: tc.find(comment) except TwillAssertionError: pass else: self.fail("Comment should not be saved") pass
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)
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))
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')
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)
def test_default(self): """The assign-to field will default to the ticket's current owner. """ ticket_id = self._tester.create_ticket(self.__class__.__name__, info={'owner': 'lammy'}) self._tester.go_to_ticket(ticket_id) tc.find('The owner will be changed from ' '<span class="trac-author">lammy</span>') tc.find('<input type="text" name="action_reassign_reassign_owner"' ' value="lammy" id="action_reassign_reassign_owner" />')
def runTest(self): """Repository with an invalid path is rendered with an error message on the repository admin page. """ self._tester.go_to_admin("Repositories") tc.formvalue('trac-addrepos', 'name', 'InvalidRepos') tc.formvalue('trac-addrepos', 'dir', '/the/invalid/path') tc.submit() tc.find((u'<span class="missing" title="[^"]*">' u'/the/\u200binvalid/\u200bpath</span>').encode('utf-8'))
def runTest(self): """Create a permissions group""" self._tester.go_to_admin("Permissions") tc.find('Manage Permissions') tc.formvalue('addperm', 'gp_subject', 'somegroup') tc.formvalue('addperm', 'action', 'REPORT_CREATE') tc.submit() somegroup = unicode_to_base64('somegroup') REPORT_CREATE = unicode_to_base64('REPORT_CREATE') tc.find('%s:%s' % (somegroup, REPORT_CREATE))
def runTest(self): self.tester.login_as(Usernames.admin) custom_type = 'with-dashes' custom_type_alias = 'With-Dashes' self.tester.create_new_ticket_type(custom_type, alias=custom_type_alias) self.go_to_admin_links_page() self.create_link('Bug', custom_type_alias, 'bug', custom_type) self.go_to_admin_links_page() tc.find('bug-with-dashes">With-Dashes</a>') tc.find('bug-with-dashes">Bug</a>')
def runTest(self): """Create a directory tree in the repository""" # This should probably use the svn bindings... directories = [] for component in ('component1', 'component2'): directories.append(component) for subdir in ('branches', 'tags', 'trunk'): directories.append('/'.join([component, subdir])) commit_message = 'Create component trees.' self._testenv.svn_mkdir(directories, commit_message) browser_url = self._tester.url + '/browser' tc.go(browser_url) tc.url(browser_url) tc.find('component1') tc.find('component2') tc.follow('Last Change') tc.url(self._tester.url + '/changeset/1/') tc.find(commit_message) for directory in directories: tc.find(directory) tc.back() tc.follow('Revision Log') # (Note that our commit log message is short enough to avoid # truncation.) tc.find(commit_message) tc.follow('Timeline') # (Note that our commit log message is short enough to avoid # truncation.) tc.find(commit_message) tc.formvalue('prefs', 'ticket', False) tc.formvalue('prefs', 'milestone', False) tc.formvalue('prefs', 'wiki', False) tc.submit() tc.find('by.*admin') # (Note that our commit log message is short enough to avoid # truncation.) tc.find(commit_message)
def runTest(self): """Add a file to the repository and verify it is in the browser""" # Add a file to Subversion tempfilename = random_word() + '_repo_browse.txt' fulltempfilename = 'component1/trunk/' + tempfilename revision = self._testenv.svn_add(fulltempfilename, random_page()) # Verify that it appears in the browser view: browser_url = self._tester.url + '/browser' tc.go(browser_url) tc.url(browser_url) tc.find('component1') tc.follow('component1') tc.follow('trunk') tc.follow(tempfilename) self._tester.quickjump('[%s]' % revision) tc.find('Changeset %s' % revision) tc.find('admin') tc.find('Add %s' % fulltempfilename) tc.find('1 added') tc.follow('Timeline') tc.find('Add %s' % fulltempfilename)
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'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'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't have the required permissions." % page_name) finally: # Restore pre-test state. self._tester.login('admin') self._testenv.revoke_perm('anonymous', 'WIKI_CREATE')
def runTest(self): """Set default handler from the Basic Settings page.""" # Confirm default value. self._tester.go_to_admin("Basic Settings") tc.find(r'<option selected="selected" value="WikiModule">' r'WikiModule</option>') tc.go(self._tester.url) tc.find("Welcome to Trac") # Set to another valid default handler. self._tester.go_to_admin("Basic Settings") tc.formvalue('modbasic', 'default_handler', 'TimelineModule') tc.submit() tc.find("Your changes have been saved.") tc.find(r'<option selected="selected" value="TimelineModule">' r'TimelineModule</option>') tc.go(self._tester.url) tc.find(r'<h1>Timeline</h1>') # Set to valid disabled default handler. try: self._testenv.set_config('components', 'trac.timeline.web_ui.TimelineModule', 'disabled') self._tester.go_to_admin("Basic Settings") tc.find(r'<option value="TimelineModule">TimelineModule</option>') tc.find(r'<span class="hint">\s*TimelineModule is not a valid ' r'IRequestHandler or is not enabled.\s*</span>') tc.go(self._tester.url) tc.find(r'<h1>Configuration Error</h1>') tc.find(r'Cannot find an implementation of the ' r'<code>IRequestHandler</code> interface named ' r'<code>TimelineModule</code>') finally: self._testenv.remove_config('components', 'trac.timeline.web_ui.timelinemodule') # Set to invalid default handler. try: self._testenv.set_config('trac', 'default_handler', 'BatchModifyModule') self._tester.go_to_admin("Basic Settings") tc.find(r'<option value="BatchModifyModule">BatchModifyModule' r'</option>') tc.find(r'<span class="hint">\s*BatchModifyModule is not a valid ' r'IRequestHandler or is not enabled.\s*</span>') tc.formvalue('modbasic', 'default_handler', 'BatchModifyModule') tc.submit() # Invalid value should not be replaced on submit tc.find(r'<option value="BatchModifyModule">BatchModifyModule' r'</option>') tc.find(r'<span class="hint">\s*BatchModifyModule is not a valid ' r'IRequestHandler or is not enabled.\s*</span>') tc.go(self._tester.url) tc.find(r'<h1>Configuration Error</h1>') tc.find(r'<code>BatchModifyModule</code> is not a valid default ' r'handler.') finally: self._testenv.set_config('trac', 'default_handler', 'WikiModule')
def runTest(self): """Admin modify milestone details""" name = self._tester.create_milestone() milestone_url = self._tester.url + '/admin/ticket/milestones' def go_to_milestone_detail(): tc.go(milestone_url) tc.url(milestone_url) tc.follow(name) tc.url(milestone_url + '/' + name) # Modify the details of the milestone go_to_milestone_detail() tc.formvalue('edit', 'due', True) tc.formvalue('edit', 'description', 'Some description.') tc.submit('save') tc.url(milestone_url) # Milestone is not closed self._tester.go_to_roadmap() tc.find(name) # Cancel more modifications and modification are not saved go_to_milestone_detail() tc.formvalue('edit', 'description', '~~Some other description.~~') tc.submit('cancel') tc.url(milestone_url) self._tester.go_to_roadmap() tc.find('Some description.') tc.follow(name) tc.find('Some description.') # Milestone is readonly when user doesn't have MILESTONE_MODIFY self._tester.logout() self._testenv.grant_perm('user', 'TICKET_ADMIN') self._tester.login('user') go_to_milestone_detail() try: tc.find(r'<input[^>]+id="name"[^>]+readonly="readonly"') tc.find(r'<input[^>]+id="due"[^>]+disabled="disabled"') tc.find(r'<input[^>]+id="duedate"[^>]+readonly="readonly"') tc.find(r'<input[^>]+id="completed"[^>]+disabled="disabled"') tc.find(r'<input[^>]+id="completeddate"[^>]+readonly="readonly"') tc.find(r'<textarea[^>]+id="description"[^>]+readonly="readonly"') tc.find(r'<input[^>]+name="save"[^>]+disabled="disabled"') tc.submit('cancel', 'edit') tc.url(milestone_url) finally: self._tester.logout() self._testenv.revoke_perm('user', 'TICKET_ADMIN') self._tester.login('admin')
def runTest(self): """Tests for the Copy Permissions functionality added in https://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')
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))
def runTest(self): """Test for regression of https://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'\s+'.join("Please contact your Trac administrator " "to enable existing translations".split()) 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')
def runTest(self): self._tester.go_to_admin("Permissions") tc.find('<span title="MILESTONE_VIEW">MILESTONE_VIEW</span>') tc.find('<span title="WIKI_VIEW">WIKI_VIEW</span>')
def runTest(self): """Admin create duplicate severity""" name = "DuplicateSeverity" self._tester.create_severity(name) self._tester.create_severity(name) tc.find(escape('Severity value "%s" already exists' % name))
def runTest(self): """Admin create duplicate resolution""" name = "DuplicateResolution" self._tester.create_resolution(name) self._tester.create_resolution(name) tc.find(escape('Resolution value "%s" already exists' % name))
def runTest(self): """Admin remove no selected priority""" priority_url = self._tester.url + "/admin/ticket/priority" tc.go(priority_url) tc.submit('remove', formname='enumtable') tc.find('No priority selected')
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))
def runTest(self): """Admin remove no selected milestone""" milestone_url = self._tester.url + "/admin/ticket/milestones" tc.go(milestone_url) tc.submit('remove', formname='milestone_table') tc.find('No milestone selected')
def runTest(self): """Check plugin settings.""" self._tester.go_to_admin("Plugins") tc.find('Manage Plugins') tc.find('Install Plugin')
def runTest(self): """Validate the About page.""" tc.follow(r"\bAbout Trac\b") tc.find(r"<h1>About Trac</h1>") tc.find(r"<h2>System Information</h2>") tc.find(r"<h2>Configuration</h2>")
def runTest(self): """Delete a wiki page.""" # Delete page with single version. name = self._tester.create_wiki_page() self._tester.go_to_wiki(name) tc.formvalue('delete', 'action', 'delete') tc.submit('delete_page') tc.find("Are you sure you want to completely delete this page?") tc.notfind("The following attachments will also be deleted:") tc.submit('delete', 'delete-confirm') tc.find("The page %s has been deleted." % name) tc.url(self._tester.url) # Delete page with attachment. name = self._tester.create_wiki_page() filename = self._tester.attach_file_to_wiki(name) self._tester.go_to_wiki(name) tc.formvalue('delete', 'action', 'delete') tc.submit('delete_page') tc.find("Are you sure you want to completely delete this page?") tc.find("The following attachments will also be deleted:") tc.find(filename) tc.submit('delete', 'delete-confirm') tc.find("The page %s has been deleted." % name) tc.url(self._tester.url) # Delete page with multiple versions. name = self._tester.create_wiki_page(content="Initial content.") self._tester.edit_wiki_page(name, content="Revised content.") self._tester.go_to_wiki(name) tc.formvalue('delete', 'action', 'delete') tc.submit('delete_page') tc.find("Are you sure you want to completely delete this page?") tc.find(r'Removing all\s+<a href="/wiki/%s\?action=history&' r'version=2">2 versions</a>\s+of the page' % name) tc.notfind("The following attachments will also be deleted:") tc.submit('delete', 'delete-confirm') tc.find("The page %s has been deleted." % name) tc.url(self._tester.url)
def runTest(self): pagename = self._tester.create_wiki_page() self._tester.edit_wiki_page(pagename) url = self._tester.url tc.follow(r"\bHistory\b") tc.url(url + r'/wiki/%s\?action=history' % pagename) version_link = ( '<td class="version">[ \n]*' '<a href="/wiki/%(pagename)s\?version=%%(version)s"' '[ \n]*title="View this version">%%(version)s[ \n]*</a>' % { 'pagename': pagename }) tc.find(version_link % {'version': 1}) tc.find(version_link % {'version': 2}) tc.find(r'<th class="comment">Comment</th>') tc.formvalue('history', 'old_version', '1') tc.formvalue('history', 'version', '2') tc.submit() tc.url(r'%s/wiki/%s\?action=diff&version=2&old_version=1' % (url, pagename)) tc.find(r'<a href="/wiki/%s\?version=1">Version 1</a>' % pagename) tc.find(r'<a href="/wiki/%s\?version=2">Version 2</a>' % pagename) tc.find(r'<a href="/wiki/%(name)s">%(name)s</a>' % {'name': pagename})
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.')
def runTest(self): """Admin milestone listing.""" name1 = self._tester.create_milestone() self._tester.create_ticket(info={'milestone': name1}) name2 = self._tester.create_milestone() milestone_url = self._tester.url + '/admin/ticket/milestones' tc.go(milestone_url) tc.url(milestone_url) tc.find(r'<a href="/admin/ticket/milestones/%(name)s">%(name)s</a>' % {'name': name1}) m1_query_link = r'<a href="/query\?group=status&' \ r'milestone=%(name)s">1</a>' % {'name': name1} tc.find(m1_query_link) tc.find(r'<a href="/admin/ticket/milestones/%(name)s">%(name)s</a>' % {'name': name2}) tc.notfind(r'<a href="/query\?group=status&milestone=%(name)s">' r'0</a>' % {'name': name2}) apply_submit = '<input type="submit" name="apply" ' \ 'value="Apply changes" />' clear_submit = '<input type="submit"[ \t\n]+title="Clear default ' \ 'ticket milestone and default retargeting milestone"' \ '[ \t\n]+name="clear" value="Clear defaults" />' tc.find(apply_submit) tc.find(clear_submit) tc.find('<input type="radio" name="ticket_default" value="%(name)s"/>' % {'name': name1}) tc.find('<input type="radio" name="retarget_default" value="%(name)s"/>' % {'name': name1}) # TICKET_ADMIN is required to change the ticket default and retarget # default configuration options. TICKET_VIEW is required for the # milestone tickets query link to be present. try: self._testenv.grant_perm('user', 'MILESTONE_ADMIN') self._testenv.revoke_perm('anonymous', 'TICKET_VIEW') self._tester.go_to_front() self._tester.logout() self._tester.login('user') tc.go(milestone_url) tc.notfind(apply_submit) tc.notfind(clear_submit) tc.find('<input type="radio" name="ticket_default" ' 'disabled="disabled" value="%(name)s"/>' % {'name': name1}) tc.find('<input type="radio" name="retarget_default" ' 'disabled="disabled" value="%(name)s"/>' % {'name': name1}) tc.notfind(m1_query_link) finally: self._testenv.revoke_perm('user', 'MILESTONE_ADMIN') self._testenv.grant_perm('anonymous', 'TICKET_VIEW') self._tester.logout() self._tester.login('admin')
def runTest(self): """Set default handler.""" # Project default_handler is selected. self._tester.go_to_preferences("User Interface") tc.notfind(r'<option[^>]+selected="selected"') tc.find("Default \(WikiModule\)") try: # Project default handler still selected after value is changed. hint = "SearchModule is not a valid IRequestHandler or is not" \ " enabled\." self._testenv.set_config('trac', 'default_handler', 'SearchModule') self._tester.go_to_preferences("User Interface") tc.notfind('<option[^>]+selected="selected"') tc.find("Default \(SearchModule\)") tc.notfind(hint) # Project default handler still selected after module is disabled. component = 'trac.search.web_ui.*' self._testenv.set_config('components', component, 'disabled') self._tester.go_to_preferences("User Interface") try: tc.notfind('<option[^>]+selected="selected"') tc.find(r"Default \(SearchModule\)") tc.find(hint) finally: self._testenv.remove_config('components', component) finally: self._testenv.set_config('trac', 'default_handler', 'WikiModule') # Set session default handler and navigate to base URL. tc.formvalue('userprefs', 'default_handler', 'TimelineModule') tc.submit() tc.find("Your preferences have been saved\.") tc.find('<option[^>]+selected="selected"[^>]+TimelineModule') self._tester.go_to_front() tc.find("<h1>Timeline</h1>") # Clear session default handler. self._tester.go_to_preferences("User Interface") tc.formvalue('userprefs', 'default_handler', '') tc.submit() tc.find("Your preferences have been saved\.") tc.notfind(r'<option[^>]+selected="selected"') tc.find("Default \(WikiModule\)")
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 %s does not exist" % tag.strong(pagename))
def test_set_owner_one_choice(self): """When using the workflow operation `may_set_owner` with a specific single-element list of available owners, the assign-to field will become a dropdown with two options if the current owner is not the single specified option. It will be a text field, and will not give the end user any choices at all, if and only if the current owner is the single specified option. """ 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.find('The owner will be changed from ' '<span class="trac-author">lammy</span>') tc.find('<select id="action_reassign_reassign_owner"') tc.notfind('<input type="hidden" ' 'name="action_reassign_reassign_owner" ' 'value="alice" id="action_reassign_reassign_owner" />') tc.notfind('The owner will be changed from ' '<span class="trac-author">lammy<span> to ' '<span class="trac-author">alice</span>') tc.find('<option selected="selected" value="lammy">lammy</option>') tc.find('<option value="alice">alice</option>') self.env.config.set('ticket-workflow', 'reassign.set_owner', "lammy") 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="lammy" />') tc.find('The owner will remain ' '<span class="trac-author">lammy</span>') tc.notfind( '<option selected="selected" value="lammy">lammy</option>') finally: self.env.config.remove('ticket-workflow', 'reassign.set_owner')
def click_rename(): tc.formvalue('rename', 'action', 'rename') tc.submit() tc.url(page_url + r'\?action=rename') tc.find("New name:")
def runTest(self): """Admin create duplicate type""" name = "DuplicateType" self._tester.create_type(name) self._tester.create_type(name) tc.find(escape('Type value "%s" already exists' % name))
def runTest(self): from trac.util.translation import get_available_locales, has_babel babel_hint_lang = "Install Babel for extended language support." babel_hint_date = "Install Babel for localized date formats." catalog_hint = "Message catalogs have not been compiled." language_select = '<select name="default_language">' disabled_language_select = \ '<select disabled="disabled" name="default_language" ' \ 'title="Translations are currently unavailable">' self._tester.go_to_admin("Basic Settings") if has_babel: tc.notfind(babel_hint_lang) tc.notfind(babel_hint_date) if get_available_locales(): tc.find(language_select) tc.notfind(catalog_hint) else: tc.find(disabled_language_select) tc.find(catalog_hint) else: tc.find(disabled_language_select) tc.find(babel_hint_lang) tc.find(babel_hint_date) tc.notfind(catalog_hint)
def runTest(self): """Admin remove no selected component""" component_url = self._tester.url + "/admin/ticket/components" tc.go(component_url) tc.submit('remove', formname='component_table') tc.find('No component selected')
def runTest(self): """Admin remove no selected version""" version_url = self._tester.url + "/admin/ticket/versions" tc.go(version_url) tc.submit('remove', formname='version_table') tc.find('No version selected')
def runTest(self): """Admin create duplicate priority""" name = "DuplicatePriority" self._tester.create_priority(name) self._tester.create_priority(name) tc.find('Priority %s already exists' % name)
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')