def test_control_lookup(self): self.browser.get( self.url("/controls/catalogs/NIST_SP-800-53_rev4/control/au-2")) wait_for_sleep_after( lambda: self.assertInNodeText("AU-2", "#control-heading")) wait_for_sleep_after( lambda: self.assertInNodeText("Audit Events", "#control-heading"))
def create_fill_statement_form(self, name, statement, part, status, statusvalue, remarks, num): """ In the component statements tab create and then fill a new component statement with the given information. """ self.click_components_tab() # Click to add new component statement self.click_element("#new_component_statement") # Open the new component form open try: new_comp_btn = self.browser.find_element_by_link_text( "New Component Statement") except: new_comp_btn = self.browser.find_element_by_id( f"producer_element-{num}-title") new_comp_btn.click() # Fill out form wait_for_sleep_after(lambda: self.browser.find_element_by_id( "producer_element_name").send_keys(name)) self.browser.find_elements_by_name("body")[-1].send_keys(statement) self.browser.find_elements_by_name("pid")[-1].send_keys(part) select = self.dropdown_option(status) select.select_by_value(statusvalue) self.browser.find_elements_by_name("remarks")[-1].send_keys(remarks) # Save form self.browser.find_elements_by_name("save")[-1].click() self.browser.refresh()
def start_invitation(username): # Fill out the invitation modal. # self.select_option_by_visible_text('#invite-user-select', username) # This is for selecting user from dropdown list wait_for_sleep_after( lambda: self.fill_field("input#invite-user-email", username)) wait_for_sleep_after(lambda: self.click_element( "#invitation_modal button.btn-submit"))
def test_display_impact_level(self): """ Tests for project page mini compliance dashboard """ # Log in, create a new project. self._login() self._new_project() # On project page? wait_for_sleep_after(lambda: self.assertInNodeText( "I want to answer some questions", "#project-title")) # Display imact level testing # New project should not be categorized self.assertInNodeText("Mission Impact: Not Categorized", "#systems-security-sensitivity-level") # Update impact level # Get project.system.root_element to attach statement holding fisma impact level project = self.current_project fil = "Low" # Test change and test system security_sensitivity_level set/get methods project.system.set_security_sensitivity_level(fil) # Check value changed worked self.assertEqual(project.system.get_security_sensitivity_level, fil) # Refresh project page self.click_element('#menu-btn-project-home') # See if project page has changed wait_for_sleep_after(lambda: self.assertInNodeText( "low", "#systems-security-sensitivity-level")) impact_level_smts = project.system.root_element.statements_consumed.filter( statement_type=StatementTypeEnum.SECURITY_SENSITIVITY_LEVEL.name) self.assertEqual(impact_level_smts.count(), 1)
def test_deployments_page_exists(self): # login as the first user and create a new project self._login() self._new_project() # systemid = System.objects.all().first() project = Project.objects.all().last() system = project.system self.navigateToPage(f"/systems/{system.id}/deployments") wait_for_sleep_after(lambda: self.assertInNodeText( "New Deployment", ".systems-element-button")) # # Add deault deployments to system deployment = Deployment(name="Training", description="Training environment", system=system) deployment.save() # Does new deployment appear on deployments list? self.navigateToPage(f"/systems/{system.id}/deployments") var_sleep(3) # wait for page to open wait_for_sleep_after(lambda: self.assertInNodeText( "New Deployment", ".systems-element-button"))
def _accept_invitation(self, username): # Assumes an invitation email was sent. # Extract the URL in the email and visit it. invitation_body = self.pop_email().body invitation_url_pattern = re.escape(self.url("/invitation/")) + r"\S+" self.assertRegex(invitation_body, invitation_url_pattern) m = re.search(invitation_url_pattern, invitation_body) self.browser.get(m.group(0)) # Since we're not logged in, we hit the invitation splash page. wait_for_sleep_after(lambda: self.click_element('#button-sign-in')) wait_for_sleep_after( lambda: self.assertRegex(self.browser.title, "Sign In"))
def _new_project(self): self.browser.get(self.url("/projects")) self.click_element("#new-project") # Select Portfolio self.select_option_by_visible_text('#id_portfolio', self.user.username) self.click_element("#select_portfolio_submit") # Start a project wait_for_sleep_after(lambda: self.click_element(".app[data-app='project/simple_project'] .view-app")) # var_sleep(10.5) self.click_element("#start-project") # wait_for_sleep_after(lambda: self.click_element("#start-project")) wait_for_sleep_after(lambda: self.assertRegex(self.browser.title, "I want to answer some questions on Q."))
def _new_project(self): self.browser.get(self.url("/store")) # wait_for_sleep_after(lambda: self.click_element("#new-project-link-from-projects")) var_sleep(1) # Click Add Button wait_for_sleep_after(lambda: self.click_element( ".app-form[data-app='project/simple_project'] .start-app")) wait_for_sleep_after(lambda: self.assertRegex( self.browser.title, "I want to answer some questions on Q.")) m = re.match(r"http://.*?/projects/(\d+)/", self.browser.current_url) self.current_project = Project.objects.get(id=m.group(1))
def test_import_tracker(self): """Tests that imports are tracked correctly.""" self._login() url = self.url(f"/controls/components") # component library self.browser.get(url) # Test initial import of Component(s) and Statement(s) self.click_element('a#import_records_link') current_path = urlparse(self.browser.current_url).path self.assertEqual('/controls/import_records', current_path) import_record_links = self.browser.find_elements_by_class_name( 'import_record_detail_link') self.assertEqual(len(import_record_links), 0) # Create an Import Record with a component and statement helper = ControlTestHelper() helper.create_simple_import_record() self.browser.refresh() import_record_links = wait_for_sleep_after( lambda: self.browser.find_elements_by_class_name( 'import_record_detail_link')) self.assertEqual(len(import_record_links), 1)
def test_update_project_json_import(self): """ Testing the update of a project through project JSON import and ingestion of components and their statements """ # login as the first user and create a new project self._login() self._new_project() # Checks the number of projects and components before the import # The number of projects should be 2 to start: # - the system project representing the organization (legacy) # - the sample project created during setup of GovReady EXISTING_PROJECT_COUNT = 2 self.assertEqual(Project.objects.all().count(), EXISTING_PROJECT_COUNT) self.assertEqual( Element.objects.all().exclude(element_type='system').count(), 0) ## Update current project # click import project button, opening the modal # wait_for_sleep_after(lambda: self.click_element("#menu-btn-project-import")) self.click_element("#menu-btn-project-import") file_input = self.browser.find_element_by_css_selector("#id_file") file_path = os.getcwd() + "/fixtures/test_project_import_data.json" # convert filepath if necessary and send keys self.filepath_conversion(file_input, file_path, "sendkeys") self.browser.find_element_by_id("import_project_submit").click() # Check the new number of projects, and validate that it's the same project_num = Project.objects.all().count() self.assertEqual(project_num, EXISTING_PROJECT_COUNT) # Has the updated name? wait_for_sleep_after(lambda: self.assertEqual( Project.objects.all()[project_num - 1].title, "New Test Project")) # Components and their statements? self.assertEqual( Element.objects.all().exclude(element_type='system').count(), 1) self.assertEqual( Element.objects.all().exclude(element_type='system')[0].name, "test component 1") try: self.assertEqual(Statement.objects.all().count(), 1) except: self.assertEqual(Statement.objects.all().count(), 4)
def test_update_project_json_import(self): """ Testing the update of a project through project JSON import and ingestion of components and their statements """ # login as the first user and create a new project self._login() self._new_project() # Checks the number of projects and components before the import self.assertEqual(Project.objects.all().count(), 3) self.assertEqual( Element.objects.all().exclude(element_type='system').count(), 0) ## Update current project # click import project button, opening the modal self.click_element("#btn-import-project") ## select through the modal information needed and browse for the import needed self.select_option_by_visible_text("#id_appsource_compapp", "project") # The selection variable found by id select = Select( self.browser.find_element_by_id("id_appsource_version_id")) # Select the last option by index selectLen = len(select.options) select.select_by_index(selectLen - 1) file_input = self.browser.find_element_by_css_selector("#id_file") file_path = os.getcwd() + "/fixtures/test_project_import_data.json" # convert filepath if necessary and send keys self.filepath_conversion(file_input, file_path, "sendkeys") self.browser.find_element_by_id("import_component_submit").click() # Check the new number of projects, and validate that it's the same project_num = Project.objects.all().count() self.assertEqual(project_num, 3) # Has the updated name? wait_for_sleep_after(lambda: self.assertEqual( Project.objects.all()[project_num - 1].title, "New Test Project")) # Components and their statements? self.assertEqual( Element.objects.all().exclude(element_type='system').count(), 1) try: self.assertEqual(Statement.objects.all().count(), 3) except: self.assertEqual(Statement.objects.all().count(), 6)
def test_edit_portfolio(self): """ Editing a portfolio's title and/or description provides appropriate validation and messaging """ # journey to portfolios and ensure i have multiple portfolios if not then create new portfolios self._login() self.browser.get(self.url("/portfolios")) # Navigate to the portfolio form self.click_element_with_link_text("Portfolios") # Click Create Portfolio button self.click_element("#new-portfolio") var_sleep(0.5) # Fill in form wait_for_sleep_after(lambda: self.fill_field("#id_title", "Test 1")) self.fill_field("#id_description", "Test 1 portfolio") # Submit form self.click_element("#create-portfolio-button") # Test we are on portfolio page we just created var_sleep(0.35) wait_for_sleep_after(lambda: self.assertRegex( self.browser.title, "Test 1 Portfolio - GovReady-Q")) # Navigate to portfolios self.browser.get(self.url("/portfolios")) # Navigate to portfolios self.browser.get(self.url("/portfolios")) # Click on the pencil anchor tag to edit self.browser.find_elements_by_class_name( "portfolio-project-link")[-1].click() # Edit title to a real new name and press update self.clear_and_fill_field("#id_title", "new me") self.clear_and_fill_field("#id_description", "new me portfolio") # Submit form self.click_element("#edit_portfolio_submit") # Verify new portfolio name is listed under portfolios self.assertIn("new me", self._getNodeText("#portfolio_new\ me")) # Verify 'updated' message is correct self.assertIn("The portfolio 'new me' has been updated.", self._getNodeText("div.alert.fade.in.alert-info")) # verify new description by journeying back to edit_form self.browser.find_elements_by_class_name( "portfolio-project-link")[-1].click()
def _upload_discussion_image(self, img_css_selector): """ Upload an image in a discussion section """ var_sleep(.5) self.click_element("#discussion .comment-input button.btn-primary") var_sleep(1.5)# Give time for the image to upload. img = wait_for_sleep_after(lambda: self.browser.find_element_by_css_selector(img_css_selector) ) return img
def test_portfolio_projects(self): """ Ensure key parts of the portfolio page """ # Login as authenticated user self.client.force_login(user=self.user) # Reset login self.browser.get(self.url("/accounts/logout/")) self._login() # If the above is not done a new project cannot be created self._new_project() portfolio_id = Project.objects.last().portfolio.id url = reverse('portfolio_projects', args=[portfolio_id]) self.browser.get(self.url(url)) wait_for_sleep_after( lambda: self.assertRegex(self.browser.title, "me-2 Portfolio")) self.assertInNodeText("I want to answer", '.portfolio-project-link')
def test_update_project_json_import(self): """ Testing the update of a project through project JSON import and ingestion of components and their statements """ # login as the first user and create a new project self._login() self._new_project() # Checks the number of projects and components before the import self.assertEqual(Project.objects.all().count(), 3) self.assertEqual(Element.objects.all().exclude(element_type='system').count(), 0) ## Update current project # click import project button, opening the modal self.click_element("#btn-import-project") file_input = self.browser.find_element_by_css_selector("#id_file") file_path = os.getcwd() + "/fixtures/test_project_import_data.json" # convert filepath if necessary and send keys self.filepath_conversion(file_input, file_path, "sendkeys") self.browser.find_element_by_id("import_component_submit").click() # Check the new number of projects, and validate that it's the same project_num = Project.objects.all().count() self.assertEqual(project_num, 3) # Has the updated name? wait_for_sleep_after(lambda: self.assertEqual(Project.objects.all()[project_num - 1].title, "New Test Project")) # Components and their statements? self.assertEqual(Element.objects.all().exclude(element_type='system').count(), 1) self.assertEqual(Element.objects.all().exclude(element_type='system')[0].name, "SecGet, Endpoint Security System") try: self.assertEqual(Statement.objects.all().count(), 4) except: self.assertEqual(Statement.objects.all().count(), 8)
def test_component_import_oscal_json(self): self._login() url = self.url(f"/controls/components")# component library self.browser.get(url) element_count_before_import = Element.objects.filter(element_type="system_element").count() statement_count_before_import = Statement.objects.filter(statement_type=StatementTypeEnum.CONTROL_IMPLEMENTATION_PROTOTYPE.value).count() # Test initial import of Component(s) and Statement(s) self.click_element('a#component-import-oscal') app_root = os.path.dirname(os.path.realpath(__file__)) oscal_json_path = os.path.join(app_root, "data/test_data", "test_oscal_component.json") file_input = self.find_selected_option('input#id_file') oscal_json_path = self.filepath_conversion(file_input, oscal_json_path, "sendkeys") self.click_element('input#import_component_submit') var_sleep(2) element_count_after_import = wait_for_sleep_after(lambda: Element.objects.filter(element_type="system_element").count()) wait_for_sleep_after(lambda: self.assertEqual(element_count_before_import + 2, element_count_after_import)) statement_count_after_import = Statement.objects.filter(statement_type=StatementTypeEnum.CONTROL_IMPLEMENTATION_PROTOTYPE.value).count() self.assertEqual(statement_count_before_import + 4, statement_count_after_import) # Test file contains 6 Statements, but only 4 get imported # because one has an improper Catalog # and another has an improper Control # but we can't test individual statements because the UUIDs are randomly generated and not consistent # with the OSCAL JSON file. So we simply do a count. # Test that duplicate Components are re-imported with a different name and that Statements get reimported wait_for_sleep_after(lambda: self.click_element('a#component-import-oscal')) file_input = self.find_selected_option('input#id_file') # Using converted keys from above file_input.send_keys(oscal_json_path) self.click_element('input#import_component_submit') element_count_after_duplicate_import = wait_for_sleep_after(lambda: Element.objects.filter(element_type="system_element").count()) self.assertEqual(element_count_after_import + 2, element_count_after_duplicate_import) original_import_element_count = Element.objects.filter(name='Test OSCAL Component1').count() self.assertEqual(original_import_element_count, 1) duplicate_import_element_count = Element.objects.filter(name='Test OSCAL Component1 (1)').count() self.assertEqual(duplicate_import_element_count, 1) statement_count_after_duplicate_import = Statement.objects.filter( statement_type=StatementTypeEnum.CONTROL_IMPLEMENTATION_PROTOTYPE.value).count() self.assertEqual(statement_count_after_import + 4, statement_count_after_duplicate_import)
def test_create_portfolio_project(self): # Create new project within portfolio self._login() self._new_project() # Create new portfolio wait_for_sleep_after(lambda: self.browser.get(self.url("/portfolios"))) wait_for_sleep_after(lambda: self.click_element("#new-portfolio")) self.fill_field("#id_title", "Security Projects") self.fill_field("#id_description", "Project Description") self.click_element("#create-portfolio-button") wait_for_sleep_after( lambda: self.assertRegex(self.browser.title, "Security Projects"))
def test_component_download_oscal_json(self): self._login() url = self.url( f"/systems/{self.system.id}/component/{self.component.id}") self.browser.get(url) self.click_element('a[href="#oscal"]') # sigh; selenium doesn't really let us find out the name of the # downloaded file, so let's make sure it doesn't exist before we # download # definite race condition possibility if self.json_download.is_file(): self.json_download.unlink() elif os.path.isfile(self.json_download.name): os.remove(self.json_download.name) wait_for_sleep_after( lambda: self.click_element("a#oscal_download_json_link")) var_sleep(2) # assert download exists! try: # The following test FAILS on MacOS when tests run in HEADLESS mode. # Test passes when tests run in visible mode. # See: https://github.com/SeleniumHQ/selenium/issues/5292#issuecomment-544264234 # To use visible mode, add to environment.json file ` "test_visible": true ` # See: https://govready-q.readthedocs.io/en/latest/testing-for-govready-q/automated-testing.html#for-developers self.assertTrue(self.json_download.is_file()) wait_for_sleep_after( lambda: self.assertTrue(self.json_download.is_file())) filetoopen = self.json_download except: wait_for_sleep_after(lambda: self.assertTrue( os.path.isfile(self.json_download.name))) # assert that it is valid JSON by trying to load it filetoopen = self.json_download.name with open(filetoopen, 'r') as f: json_data = json.load(f) self.assertIsNotNone(json_data) if self.json_download.is_file(): self.json_download.unlink() elif os.path.isfile(self.json_download.name): os.remove(self.json_download.name)
def reset_login(): # Log out and back in as the original user. self.browser.get(self.url("/accounts/logout/")) self._login() wait_for_sleep_after(lambda: self.browser.get(project_page))
def test_discussion(self): # Log in and create a new project. self._login() self._new_project() wait_for_sleep_after(lambda: self._start_task())# wait for page to reload # Move past the introduction screen. self.assertRegex(self.browser.title, "Next Question: Module Introduction") self.click_element("#save-button") var_sleep(.8) # wait for page to reload # Click interstitial "Got it" button self.click_element("#save-button") var_sleep(.5) # We're now on the first actual question. # Start a team conversation. wait_for_sleep_after(lambda: self.click_element("#start-a-discussion")) wait_for_sleep_after(lambda: self.fill_field("#discussion-your-comment", "Hello is anyone *here*?")) wait_for_sleep_after(lambda: self.click_element("#discussion .comment-input button.btn-primary")) # Test Script injection script = "<script id='injectiontest2'>document.getElementsByTagName('body')[0]" \ ".appendChild('<div id=\\'injectiontest1\\'></div>');</script>" wait_for_sleep_after(lambda: self.fill_field("#discussion-your-comment", script)) wait_for_sleep_after(lambda: self.click_element("#discussion .comment-input button.btn-primary")) # Check that the element was *not* added to the page. with self.assertRaises(NoSuchElementException): self.browser.find_element_by_css_selector('#injectiontest1') # Check that the script tag was removed entirely. with self.assertRaises(NoSuchElementException): self.browser.find_element_by_css_selector('#injectiontest2') # Test some special characters wait_for_sleep_after(lambda: self.fill_field("#discussion-your-comment", "¥")) wait_for_sleep_after(lambda: self.click_element("#discussion .comment-input button.btn-primary")) wait_for_sleep_after(lambda: self.assertInNodeText("¥", '.comment[data-id="3"] .comment-text p'))
def test_smt_autocomplete(self): """ Testing if the textbox can autocomplete and filter for existing components """ # login as the first user and create a new project self._login() self._new_project() # TODO: Why is system being overridden/conditional. system_id will be 1 in test class and 4 in full test suite systemid = System.objects.all().first() self.navigateToPage(f"/systems/{systemid.id}/controls/selected") # Select moderate self.navigateToPage( f"/systems/{systemid.id}/controls/baseline/NIST_SP-800-53_rev4/moderate/_assign" ) # Head to the control ac-3 self.navigateToPage( f"/systems/{systemid.id}/controls/catalogs/NIST_SP-800-53_rev4/control/ac-3" ) # How many components are there currently? # Confirm the dropdown sees all components comps_dropdown = wait_for_sleep_after( lambda: self.dropdown_option("selected_producer_element_form_id")) num = len(comps_dropdown.options) # Create components self.create_fill_statement_form("Component 1", "Component body", 'a', 'status_', "Planned", "Component remarks", num) num += 1 wait_for_sleep_after(lambda: self.create_fill_statement_form( "Component 2", "Component body", 'b', 'status_', "Planned", "Component remarks", num)) num += 1 wait_for_sleep_after(lambda: self.create_fill_statement_form( "Component 3", "Component body", 'c', 'status_', "Planned", "Component remarks", num)) num += 1 wait_for_sleep_after(lambda: self.create_fill_statement_form( "Test name 1", "Component body", 'a', 'status_', "Planned", "Component remarks", num)) num += 1 wait_for_sleep_after(lambda: self.create_fill_statement_form( "Test name 2", "Component body", 'b', 'status_', "Planned", "Component remarks", num)) num += 1 wait_for_sleep_after(lambda: self.create_fill_statement_form( "Test name 3", "Component body", 'c', 'status_', "Planned", "Component remarks", num)) # Refresh page to refresh items in selection self.navigateToPage( f"/systems/{systemid.id}/controls/catalogs/NIST_SP-800-53_rev4/control/ac-3" ) wait_for_sleep_after(lambda: self.click_components_tab()) # Confirm the dropdown sees all components comps_dropdown = wait_for_sleep_after( lambda: self.dropdown_option("selected_producer_element_form_id")) self.assertEquals(len(comps_dropdown.options), 7) # Click on search bar search_comps_txtbar = self.browser.find_elements_by_id( "producer_element_search") # Type a few text combinations and make sure filtering is working # Need to click the new dropdown after sending keys ## Search for Component search_comps_txtbar[-1].click() search_comps_txtbar[-1].clear() search_comps_txtbar[-1].send_keys("Component") self.browser.find_elements_by_id( "selected_producer_element_form_id")[-1].click() # Ajax request var_sleep(1) assert len(comps_dropdown.options) == 3 ## Search for 2 search_comps_txtbar[-1].click() search_comps_txtbar[-1].clear() search_comps_txtbar[-1].send_keys("2") self.browser.find_elements_by_id( "selected_producer_element_form_id")[-1].click() # Ajax request var_sleep(1) # print("####### len(comps_dropdown.options)", len(comps_dropdown.options)) assert len(comps_dropdown.options) == 2 # Use elements from database to avoid hard-coding element ids expected elements = Element.objects.all() testname2_ele = str(elements[5].id) component2_ele = str(elements[2].id) # Add a new component based on one of the options available in the filtered dropdown ## Test name 2 has a value of 6 and Component 2 has a value of 3 self.select_option("select#selected_producer_element_form_id", testname2_ele) assert self.find_selected_option( "select#selected_producer_element_form_id").get_property( "value") == testname2_ele ## Test name 2 has a value of 6 and Component 2 has a value of 3 self.select_option("select#selected_producer_element_form_id", component2_ele) assert self.find_selected_option( "select#selected_producer_element_form_id").get_property( "value") == component2_ele # Open a modal will with component statements related to the select component prototype add_related_statements_btn = self.browser.find_elements_by_id( "add_related_statements") add_related_statements_btn[-1].click() # Ensure we can't submit no component statements and that the alert pops up. wait_for_sleep_after(lambda: self.browser.find_element_by_xpath( "//*[@id='relatedcompModal']/div/div[1]/div[4]/button").click()) # Open the first panel component_element_btn = self.browser.find_element_by_id( "related-panel-1") component_element_btn.click() select_comp_statement_check = wait_for_sleep_after( lambda: self.browser.find_element_by_name("relatedcomps")) var_sleep(1) wait_for_sleep_after(lambda: select_comp_statement_check.click()) var_sleep(1) # Add component statement submit_comp_statement = wait_for_sleep_after( lambda: self.browser.find_element_by_xpath( "//*[@id='relatedcompModal']/div/div[1]/div[4]/button")) submit_comp_statement.click()
def test_invitations(self): # Test a bunch of invitations. # Log in and create a new project. self._login() self._new_project() project_page = self.browser.current_url # And create a new task. self._start_task() task_page = self.browser.current_url # But now go back to the project page. self.browser.get(project_page) def start_invitation(username): # Fill out the invitation modal. # self.select_option_by_visible_text('#invite-user-select', username) # This is for selecting user from dropdown list wait_for_sleep_after( lambda: self.fill_field("input#invite-user-email", username)) wait_for_sleep_after(lambda: self.click_element( "#invitation_modal button.btn-submit")) def do_invitation(username): start_invitation(username) var_sleep(.5) # wait for invitation to be sent # Log out and accept the invitation as an anonymous user. self.browser.get(self.url("/accounts/logout/")) self._accept_invitation(username) def reset_login(): # Log out and back in as the original user. self.browser.get(self.url("/accounts/logout/")) self._login() wait_for_sleep_after(lambda: self.browser.get(project_page)) # Test an invitation to that project. For unknown reasons, when # executing this on CircleCI (but not locally), the click fails # because the element is not clickable -- it reports a coordinate # that's above the button in the site header. Not sure what's # happening. So load the modal using Javascript. wait_for_sleep_after( lambda: self.click_element("#menu-btn-show-project-invite")) self.browser.execute_script("invite_user_into_project()") # Toggle field to invite user by email self.browser.execute_script( "$('#invite-user-email').parent().toggle(true)") # Test an invalid email address. start_invitation("example") wait_for_sleep_after(lambda: self.assertInNodeText( "The email address is not valid.", "#global_modal") ) # make sure we get a stern message. wait_for_sleep_after(lambda: self.click_element("#global_modal button") ) # dismiss the warning. wait_for_sleep_after(lambda: self.click_element( "#menu-btn-show-project-invite")) # Re-open the invite box. self.browser.execute_script( "invite_user_into_project()") # See comment above. # Toggle field to invite user by email wait_for_sleep_after(lambda: self.browser.execute_script( "$('#invite-user-email').parent().toggle(true)")) var_sleep(3) # Adding to avoid lock do_invitation(self.user2.email) self.fill_field("#id_login", self.user2.username) self.fill_field("#id_password", self.user2.clear_password) self.click_element("form button.primaryAction") self.assertRegex(self.browser.title, "I want to answer some questions on Q" ) # user is on the project page wait_for_sleep_after(lambda: self.click_element( '#question-simple_module')) # go to the task page wait_for_sleep_after(lambda: self.assertRegex( self.browser.title, "Next Question: Module Introduction") ) # user is on the task page # reset_login() # Test an invitation to take over editing a task but without joining the project. var_sleep(.5) wait_for_sleep_after( lambda: self.click_element("#save-button") ) # pass over the Introductory question because the Help link is suppressed on interstitials wait_for_sleep_after(lambda: self.click_element('#transfer-editorship') ) # Toggle field to invite user by email self.browser.execute_script( "$('#invite-user-email').parent().toggle(true)") wait_for_sleep_after(lambda: do_invitation(self.user3.email) ) # Toggle field to invite user by email self.fill_field("#id_login", self.user3.username) self.fill_field("#id_password", self.user3.clear_password) self.click_element("form button.primaryAction") wait_for_sleep_after(lambda: self.assertRegex( self.browser.title, "Next Question: The Question") ) # user is on the task page # Test assigning existing user to a project. reset_login() self._new_project() project_page = self.browser.current_url # And create a new task. self._start_task() task_page = self.browser.current_url # But now go back to the project page. self.browser.get(project_page) wait_for_sleep_after( lambda: self.click_element("#menu-btn-show-project-invite")) # Select username "me3" wait_for_sleep_after(lambda: self.select_option_by_visible_text( '#invite-user-select', "me3")) wait_for_sleep_after(lambda: self.click_element("#invite_submit_btn")) wait_for_sleep_after(lambda: self.assertInNodeText( "me3 granted edit permission to project", ".alert"))
def test_mini_dashboard(self): """ Tests for project page mini compliance dashboard """ # Log in, create a new project. self._login() self._new_project() # On project page? # wait_for_sleep_after(lambda: self.assertInNodeText("I want to answer some questions", "#project-title")) wait_for_sleep_after(lambda: self.assertInNodeText( "I want to answer some questions", "h2")) # mini-dashboard content self.assertInNodeText("controls", "#status-box-controls") self.assertInNodeText("components", "#status-box-components") # TODO: Restore tests if #status-box-poam is displayed # self.assertInNodeText("POA&Ms", "#status-box-poams") self.assertInNodeText("compliance", "#status-box-compliance-piechart") # mini-dashbard links self.click_element('#status-box-controls') wait_for_sleep_after(lambda: self.assertInNodeText( "Selected controls", ".systems-selected-items")) # click project button wait_for_sleep_after( lambda: self.click_element("#menu-btn-project-home")) # wait_for_sleep_after(lambda: self.assertInNodeText("I want to answer some questions", "#project-title")) wait_for_sleep_after(lambda: self.assertInNodeText( "I want to answer some questions", "h2")) # test components self.click_element('#status-box-components') wait_for_sleep_after(lambda: self.assertInNodeText( "Selected components", ".systems-selected-items")) # click project button wait_for_sleep_after( lambda: self.click_element("#menu-btn-project-home")) # wait_for_sleep_after(lambda: self.assertInNodeText("I want to answer some questions", "#project-title")) wait_for_sleep_after(lambda: self.assertInNodeText( "I want to answer some questions", "h2"))
def test_create_portfolios(self): # Create a new account self.browser.get(self.url("/")) self.click_element('#tab-register') self._fill_in_signup_form("*****@*****.**", "portfolio_user") self.click_element("#signup-button") if "Warning Message" in self.browser.title: self.click_element("#btn-accept") # Go to portfolio page self.browser.get(self.url("/portfolios")) # Navigate to portfolio created on signup self.click_element_with_link_text("portfolio_user") # Test creating a portfolio using the form # Navigate to the portfolio form wait_for_sleep_after( lambda: self.click_element_with_link_text("Portfolios")) # Click Create Portfolio button self.click_element("#new-portfolio") var_sleep(0.5) # Fill in form wait_for_sleep_after(lambda: self.fill_field("#id_title", "Test 1")) self.fill_field("#id_description", "Test 1 portfolio") # Submit form self.click_element("#create-portfolio-button") # Test we are on portfolio page we just created wait_for_sleep_after(lambda: self.assertRegex( self.browser.title, "Test 1 Portfolio - GovReady-Q")) # Test we cannot create a portfolio with the same name # Navigate to the portfolio form self.click_element_with_link_text("Portfolios") # Click Create Portfolio button self.click_element("#new-portfolio") var_sleep(0.5) # Fill in form wait_for_sleep_after(lambda: self.fill_field("#id_title", "Test 1")) self.fill_field("#id_description", "Test 1 portfolio") # Submit form self.click_element("#create-portfolio-button") # We should get an error # test error wait_for_sleep_after(lambda: self.assertIn( "Portfolio name Test 1 not available.", self._getNodeText( "div.alert.alert-danger.alert-dismissable.alert-link"))) # Test uniqueness with case insensitivity # Navigate to the portfolio form self.click_element_with_link_text("Portfolios") # Click Create Portfolio button self.click_element("#new-portfolio") var_sleep(0.5) # Fill in form wait_for_sleep_after(lambda: self.fill_field("#id_title", "test 1")) # Submit form wait_for_sleep_after( lambda: self.click_element("#create-portfolio-button")) # We should get an error var_sleep(0.5) # test error wait_for_sleep_after(lambda: self.assertIn( "Portfolio name test 1 not available.", self._getNodeText( "div.alert.alert-danger.alert-dismissable.alert-link")))
def test_grant_portfolio_access(self): # Grant another member access to portfolio self._login() self.browser.get(self.url("/portfolios")) self.click_element("#portfolio_{}".format(self.user.username)) self.click_element("#grant-portfolio-access") var_sleep(.5) wait_for_sleep_after(lambda: self.select_option_by_visible_text( '#invite-user-select', 'me2')) wait_for_sleep_after( lambda: self.click_element("#invitation_modal button.btn-submit")) wait_for_sleep_after( lambda: self.assertInNodeText("me2", "#portfolio-member-me2")) # Grant another member ownership of portfolio wait_for_sleep_after( lambda: self.click_element("#me2_grant_owner_permission")) var_sleep(0.5) wait_for_sleep_after(lambda: self.assertInNodeText( "me2 (Owner)", "#portfolio-member-me2")) # Grant another member access to portfolio self.click_element("#grant-portfolio-access") self.select_option_by_visible_text('#invite-user-select', 'me3') self.click_element("#invitation_modal button.btn-submit") wait_for_sleep_after( lambda: self.assertInNodeText("me3", "#portfolio-member-me3")) # Remove another member access to portfolio self.click_element("#me3_remove_permissions") self.assertNotInNodeText("me3", "#portfolio-members") self.assertNodeNotVisible("#portfolio-member-me3")