def test_element_create(self): # Create a root_element and system e = Element.objects.create(name="New Element 2", full_name="New Element 2 Full Name", element_type="system") self.assertTrue(e.id is not None) self.assertTrue(e.name == "New Element 2") self.assertTrue(e.full_name == "New Element 2 Full Name") self.assertTrue(e.element_type == "system") e.save() s = System(root_element=e) s.save() self.assertEqual(s.root_element.name, e.name) # Create a Poam for the system smt = Statement.objects.create(sid=None, sid_class=None, pid=None, body="This is a test Poam statement.", statement_type="Poam", status="New", consumer_element=e) smt.save() poam = Poam.objects.create(statement=smt, poam_group="New POA&M Group") self.assertTrue(poam.poam_group == "New POA&M Group") # self.assertTrue(poam.name == "New Element") # self.assertTrue(poam.full_name == "New Element Full Name") # self.assertTrue(poam.element_type == "system") poam.save()
def test_security_objectives(self): """ Test set/get of Security Objective levels """ # Log in, create a new project. self._login() self._new_project() project = Project.objects.first() element = Element() element.name = project.title element.element_type = "system" element.save() # Create system system = System(root_element=element) system.save() # Link system to project project.system = system # security objectives new_security_objectives = { "security_objective_confidentiality": "low", "security_objective_integrity": "high", "security_objective_availability": "moderate" } # Setting security objectives for project's statement security_objective_smt, smt = project.system.set_security_impact_level( new_security_objectives) # Check value changed worked self.assertEqual(project.system.get_security_impact_level, new_security_objectives)
def test_assign_baseline(self): # Create root_element - no relayed controls should exist element = Element(name="sys_root_element") element.save() self.assertEqual(0, len(element.controls.all())) # Create system system = System(root_element=element) system.save() # Create a user because method expect user with correct permission user = User(email='*****@*****.**', username="******") user.save() # Assign owner permissions element.assign_edit_permissions(user) # Assign low baseline and some controls should exist result = element.assign_baseline_controls(user, 'NIST_SP-800-53_rev4', 'low') self.assertLess(110, len(element.controls.all())) self.assertGreater(135, len(element.controls.all())) # Assign moderate baseline and more controls should exist element.assign_baseline_controls(user, 'NIST_SP-800-53_rev4', 'moderate') self.assertLess(210, len(element.controls.all())) self.assertGreater(280, len(element.controls.all())) # Assign low baseline and controls should be removed element.assign_baseline_controls(user, 'NIST_SP-800-53_rev4', 'low') self.assertLess(110, len(element.controls.all())) self.assertGreater(135, len(element.controls.all()))
def setUp(self): super().setUp() self.json_download = \ self.download_path / PurePath(slugify(self.component_name)).with_suffix(".json") # print("********* self.json_download", self.json_download) # we need a system and a component root_element = Element(name="My Root Element", description="Description of my root element") root_element.save() self.system = System() self.system.root_element = root_element self.system.save() project = self.org.get_organization_project() project.system = self.system project.save() self.system.assign_owner_permissions(self.user) statement = Statement(sid='ac-1', sid_class=Catalogs.NIST_SP_800_53_rev4, body='My statement body', status='Not Implmented') statement.save() producer_element, created = Element.objects.get_or_create(name=self.component_name) statement.producer_element = producer_element statement.consumer_element = root_element statement.save() self.component = producer_element # enable experimental OpenControl support enable_experimental_opencontrol, _ = SystemSettings.objects.get_or_create(setting='enable_experimental_opencontrol') enable_experimental_opencontrol.active = True enable_experimental_opencontrol.save()
def test_export_csv(self, mockcsvexport): """ Mock post request of SSP CSV export Check if the mock can create valid ExportCSVTemplateSSPForm data. export_ssp_csv """ mockresponse = Mock() mockcsvexport.return_value = mockresponse mockresponse.POST = dict(info_system="Information System", control_id="Control ID", catalog="Control Set Version Number", shared_imps="Shared Implementation Details", private_imps="Private Implementation Details") export_csv_form = ExportCSVTemplateSSPForm(mockresponse.POST) # we need a system and a component root_element = Element(name="My Root Element", description="Description of my root element") root_element.save() self.system = System() self.system.root_element = root_element if export_csv_form.is_valid(): response = export_ssp_csv(export_csv_form.data, self.system) assert response.status_code == 200
def test_system_create(self): e = Element.objects.create(name="New Element", full_name="New Element Full Name", element_type="system") self.assertTrue(e.id is not None) self.assertTrue(e.name == "New Element") self.assertTrue(e.full_name == "New Element Full Name") self.assertTrue(e.element_type == "system") s = System(root_element=e) s.save() self.assertEqual(s.root_element.name, e.name) u2 = User.objects.create(username="******", email="*****@*****.**") # Test no permissions for user perms = get_user_perms(u2, s) self.assertTrue(len(perms) == 0) # Assign owner permissions s.assign_owner_permissions(u2) perms = get_user_perms(u2, s) self.assertTrue(len(perms) == 4) self.assertIn('add_system', perms) self.assertIn('change_system', perms) self.assertIn('delete_system', perms) self.assertIn('view_system', perms)
class ComponentUITests(OrganizationSiteFunctionalTests): component_name = "XYZZY" def setUp(self): super().setUp() self.json_download = \ self.download_path / PurePath(slugify(self.component_name)).with_suffix(".json") print("********* self.json_download", self.json_download) # we need a system and a component root_element = Element(name="My Root Element", description="Description of my root element") root_element.save() self.system = System() self.system.root_element = root_element self.system.save() project = self.org.get_organization_project() project.system = self.system project.save() self.system.assign_owner_permissions(self.user) statement = Statement(sid='ac-1', sid_class=Catalogs.NIST_SP_800_53_rev4, body='My statement body', status='Not Implmented') statement.save() producer_element, created = Element.objects.get_or_create( name=self.component_name) statement.producer_element = producer_element statement.consumer_element = root_element statement.save() self.component = producer_element # enable experimental OSCAL -and- OpenControl support enable_experimental_oscal, _ = SystemSettings.objects.get_or_create( setting='enable_experimental_oscal') enable_experimental_oscal.active = True enable_experimental_oscal.save() enable_experimental_opencontrol, _ = SystemSettings.objects.get_or_create( setting='enable_experimental_opencontrol') enable_experimental_opencontrol.active = True enable_experimental_opencontrol.save() def tearDown(self): # clean up downloaded file if linux elif dos if self.json_download.is_file(): self.json_download.unlink() elif os.path.isfile(self.json_download.name): os.remove(self.json_download.name) super().tearDown() 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) self.click_element("a#oscal_download_json_link") var_sleep(2) # need to wait for download, alas # assert download exists! try: self.assertTrue(self.json_download.is_file()) filetoopen = self.json_download except: 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 test_component_import_invalid_oscal(self): self._login() url = self.url(f"/controls/components") self.browser.get(url) 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_invalid_oscal.json") file_input = self.find_selected_option('input#id_file') self.filepath_conversion(file_input, oscal_json_path, "sendkeys") # Verify that the contents got copied correctly from the file to the textfield try: # Load contents from file with open(oscal_json_path, 'r') as f: loaded_oscal_file_json = json.load(f) # Load contents from textarea file_contents = self.find_selected_option( 'textarea#id_json_content').get_attribute("value") oscal_json_contents = json.loads(file_contents) self.assertEqual(loaded_oscal_file_json, oscal_json_contents) except ValueError: pass self.click_element('input#import_component_submit') element_count = Element.objects.filter( uuid='123456a7-b890-1234-cd56-e789fa012bcd').count() self.assertEqual(element_count, 0) statement1_count = Statement.objects.filter( uuid='1ab2c345-67d8-9e0f-1234-5a6bcd789efa').count() self.assertEqual(statement1_count, 0) statement2_count = Statement.objects.filter( uuid='2bc3d456-78e9-0f1a-2345-6b7cde890fab').count() self.assertEqual(statement2_count, 0) def test_component_import_oscal_json(self): self._login() url = self.url(f"/controls/components") self.browser.get(url) # 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') element_count = Element.objects.filter( name='Test OSCAL Component').count() self.assertEqual(element_count, 1) statement1_count = Statement.objects.filter( uuid='1ab0b252-90d3-4d2c-9785-0c4efb254dfc').count() self.assertEqual(statement1_count, 1) statement2_count = Statement.objects.filter( uuid='2ab0b252-90d3-4d2c-9785-0c4efb254dfc').count() self.assertEqual(statement2_count, 1) # Verify that statements without a proper Catalog don't get entered statement3_count = Statement.objects.filter( uuid='4ab0b252-90d3-4d2c-9785-0c4efb254dfc').count() self.assertEqual(statement3_count, 0) # Verify that statements without a proper Control don't get entered statement4_count = Statement.objects.filter( uuid='6ab0b252-90d3-4d2c-9785-0c4efb254dfc').count() self.assertEqual(statement4_count, 0) var_sleep(1) # Needed to allow page to refresh and messages to render # Test that duplicate Components and Statements are not re-imported 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 = Element.objects.filter( name='Test OSCAL Component').count() self.assertEqual(element_count, 1) statement1_count = Statement.objects.filter( uuid='1ab0b252-90d3-4d2c-9785-0c4efb254dfc').count() self.assertEqual(statement1_count, 1)
def start_app(appver, organization, user, folder, task, q, portfolio): # Begin a transaction to create the Module and Task instances for the app. with transaction.atomic(): # Create project. project = Project() project.organization = organization project.portfolio = portfolio # Save and add to folder project.save() project.set_root_task(appver.modules.get(module_name="app"), user) # Update default name to be unique by using project.id project.root_task.title_override = project.title + " " + str( project.id) project.root_task.save() if folder: folder.projects.add(project) # Log start app / new project logger.info(event="start_app", object={ "task": "project", "id": project.root_task.id, "title": project.root_task.title_override }, user={ "id": user.id, "username": user.username }) logger.info(event="new_project", object={ "object": "project", "id": project.id, "title": project.title }, user={ "id": user.id, "username": user.username }) # Create a new System element and link to project? # Top level apps should be linked to a system # Create element to serve as system's root_element # Element names must be unique. Use unique project title set above. element = Element() element.name = project.title element.element_type = "system" element.save() # Create system system = System(root_element=element) system.save() system.add_event( "SYS", f"Created new System in GovReady based on template '{appver.catalog_metadata['title']}'." ) system.info == { "created_from_template": project.title, "system_description": "New system", "id": system.id, "other_id": "~", "name": project.root_task.title_override, "organization_name": "~", "aka": "~", "impact": "~", "status": "Planned", "type": "~", "created": "~", "hosting_facility": "~", "next_audit": "~", "next_scan": "~", #"05/01/22", "security_scan": "~", "pen_test": "~", #"Scheduled for 05/05/22", "config_scan": "~", "purpose": "~", "vuln_new_30days": "~", "vuln_new_rslvd_30days": "~", "vuln_90days": "~", "risk_score": "~", "score_1": "~", "score_2": "~", "score_3": "~", "score_4": "~", "score_5": "~", } system.save() # Link system to project project.system = system project.save() # Log start app / new project logger.info(event="new_element new_system", object={ "object": "element", "id": element.id, "name": element.name }, user={ "id": user.id, "username": user.username }) # Add user as the first admin of project. ProjectMembership.objects.create(project=project, user=user, is_admin=True) # Grant owner permissions on root_element to user element.assign_owner_permissions(user) # Log ownership assignment logger.info(event="new_element new_system assign_owner_permissions", object={ "object": "element", "id": element.id, "name": element.name }, user={ "id": user.id, "username": user.username }) system.assign_owner_permissions(user) # Log ownership assignment logger.info(event="new_system assign_owner_permissions", object={ "object": "system", "id": system.root_element.id, "name": system.root_element.name }, user={ "id": user.id, "username": user.username }) # Add default deployments to system deployment = Deployment( name="Blueprint", description="Reference system archictecture design", system=system) deployment.save() deployment = Deployment( name="Dev", description="Development environment deployment", system=system) deployment.save() deployment = Deployment( name="Stage", description="Stage/Test environment deployment", system=system) deployment.save() deployment = Deployment( name="Prod", description="Production environment deployment", system=system) deployment.save() # Assign default control catalog and control profile # Use from App catalog settings try: # Get default catalog key parameters = project.root_task.module.app.catalog_metadata[ 'parameters'] catalog_key = [p for p in parameters if p['id'] == 'catalog_key'][0]['value'] # Get default profile/baseline baseline_name = [p for p in parameters if p['id'] == 'baseline'][0]['value'] # Assign profile/baseline assign_results = system.root_element.assign_baseline_controls( user, catalog_key, baseline_name) # Log result if successful if assign_results: # Log start app / new project logger.info(event="assign_baseline", object={ "object": "system", "id": system.root_element.id, "title": system.root_element.name }, baseline={ "catalog_key": catalog_key, "baseline_name": baseline_name }, user={ "id": user.id, "username": user.username }) except: # TODO catch error and return error message print( "[INFO] App could not assign catalog_key or profile/baseline.\n" ) # Assign default organization components for a system if user.has_perm('change_system', system): # Get the components from the import records of the app version import_records = appver.input_artifacts.all() for import_record in import_records: add_selected_components(system, import_record) else: # User does not have write permissions logger.info(event="change_system permission_denied", user={ "id": user.id, "username": user.username }) # TODO: Assign default org parameters if task and q: # It will also answer a task's question. ans, is_new = task.answers.get_or_create(question=q) ansh = ans.get_current_answer() if q.spec[ "type"] == "module" and ansh and ansh.answered_by_task.count( ): raise ValueError( 'The question %s already has an app associated with it.' % q.spec["title"]) ans.save_answer( None, # not used for module-type questions list([] if not ansh else ansh.answered_by_task.all()) + [project.root_task], None, user, "web") return project
def test_organizational_parameters_via_project(self): # for this test, we need a Project, System, and Organization # REMIND: it would be nice to refactor all this setup code so # it could be easily reused ... from guidedmodules.models import AppSource from guidedmodules.management.commands.load_modules import Command as load_modules AppSource.objects.all().delete() AppSource.objects.get_or_create( slug="system", is_system_source=True, defaults={ "spec": { # required system projects "type": "local", "path": "fixtures/modules/system", } } ) load_modules().handle() # load system modules AppSource.objects.create( slug="project", spec={ # contains a test project "type": "local", "path": "fixtures/modules/other", }, trust_assets=True )\ .add_app_to_catalog("simple_project") user = User.objects.create( username="******", email="*****@*****.**", is_staff=True ) org = Organization.create(name="Our Organization", slug="testorg", admin_user=user) root_element = Element(name="My Root Element", description="Description of my root element") root_element.save() system = System() system.root_element = root_element system.save() project = org.get_organization_project() project.system = system project.save() parameter_values = project.get_parameter_values(Catalogs.NIST_SP_800_53_rev4) self.assertEquals(parameter_values["ac-1_prm_2"], "at least every 3 years") # now, add an organizational setting and try again OrganizationalSetting.objects.create(organization=org, catalog_key=Catalogs.NIST_SP_800_53_rev4, parameter_key="ac-1_prm_2", value="at least every 100 years") # we should now see the organizational setting override parameter_values = project.get_parameter_values(Catalogs.NIST_SP_800_53_rev4) self.assertEquals(parameter_values["ac-1_prm_2"], "at least every 100 years")
class ComponentUITests(OrganizationSiteFunctionalTests): component_name = "XYZZY" def setUp(self): super().setUp() self.json_download = \ self.download_path / PurePath(slugify(self.component_name)).with_suffix(".json") print("********* self.json_download", self.json_download) # we need a system and a component root_element = Element(name="My Root Element", description="Description of my root element") root_element.save() self.system = System() self.system.root_element = root_element self.system.save() project = self.org.get_organization_project() project.system = self.system project.save() self.system.assign_owner_permissions(self.user) statement = Statement(sid='ac-1', sid_class=Catalogs.NIST_SP_800_53_rev4, body='My statement body', status='Not Implmented') statement.save() producer_element, created = Element.objects.get_or_create(name=self.component_name) statement.producer_element = producer_element statement.consumer_element = root_element statement.save() self.component = producer_element # enable experimental OSCAL -and- OpenControl support enable_experimental_oscal, _ = SystemSettings.objects.get_or_create(setting='enable_experimental_oscal') enable_experimental_oscal.active = True enable_experimental_oscal.save() enable_experimental_opencontrol, _ = SystemSettings.objects.get_or_create(setting='enable_experimental_opencontrol') enable_experimental_opencontrol.active = True enable_experimental_opencontrol.save() def tearDown(self): # clean up downloaded file if linux elif dos if self.json_download.is_file(): self.json_download.unlink() elif os.path.isfile(self.json_download.name): os.remove(self.json_download.name) super().tearDown() 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) self.click_element("a#oscal_download_json_link") var_sleep(2) # need to wait for download, alas # assert download exists! try: self.assertTrue(self.json_download.is_file()) filetoopen = self.json_download except: 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 test_component_import_invalid_oscal(self): self._login() url = self.url(f"/controls/components") self.browser.get(url) 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_invalid_oscal.json") file_input = self.find_selected_option('input#id_file') self.filepath_conversion(file_input, oscal_json_path, "sendkeys") element_count_before_import = Element.objects.filter(element_type="system_element").count() statement_count_before_import = Statement.objects.filter( statement_type="control_implementation_prototype").count() # Verify that the contents got copied correctly from the file to the textfield try: # Load contents from file with open(oscal_json_path, 'r') as f: loaded_oscal_file_json = json.load(f) # Load contents from textarea file_contents = self.find_selected_option('textarea#id_json_content').get_attribute("value") oscal_json_contents = json.loads(file_contents) self.assertEqual(loaded_oscal_file_json, oscal_json_contents) except ValueError: pass self.click_element('input#import_component_submit') element_count_after_import = Element.objects.filter(element_type="system_element").count() self.assertEqual(element_count_before_import, element_count_after_import) statement_count_after_import = Statement.objects.filter(statement_type="control_implementation_prototype").count() self.assertEqual(statement_count_before_import, statement_count_after_import) def test_component_import_oscal_json(self): self._login() url = self.url(f"/controls/components") 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="control_implementation_prototype").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(3) # Wait for OSCAL to be imported element_count_after_import = Element.objects.filter(element_type="system_element").count() self.assertEqual(element_count_before_import + 2, element_count_after_import) statement_count_after_import = Statement.objects.filter(statement_type="control_implementation_prototype").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. var_sleep(3) # Needed to allow page to refresh and messages to render # Test that duplicate Components are re-imported with a different name and that Statements get reimported 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') var_sleep(3) # Wait for OSCAL to be imported element_count_after_duplicate_import = 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="control_implementation_prototype").count() self.assertEqual(statement_count_after_import + 4, statement_count_after_duplicate_import) def test_import_tracker(self): """Tests that imports are tracked correctly.""" self._login() url = self.url(f"/controls/components") 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() var_sleep(1) import_record_links = self.browser.find_elements_by_class_name('import_record_detail_link') self.assertEqual(len(import_record_links), 1) def test_import_delete(self): """Tests that import deletions remove child components and statements.""" # Create an Import Record with a component and statement helper = ControlTestHelper() import_record = helper.create_simple_import_record() self._login() url = self.url(f"/controls/import_records") self.browser.get(url) self.click_element(f"a.import_record_detail_link") self.click_element(f"a#delete-import") # Test that cancel doesn't delete the import, and redirects to the component library self.click_element(f"a#cancel-import-delete") current_path = urlparse(self.browser.current_url).path self.assertEqual('/controls/components', current_path) import_records_count = ImportRecord.objects.all().count() self.assertEqual(import_records_count, 1) component_count = Element.objects.filter(import_record=import_record).count() self.assertEqual(component_count, 1) statement_count = Statement.objects.filter(import_record=import_record).count() self.assertEqual(statement_count, 1) # Test that confirming the deletion deletes the import, component, and statement url = self.url(f"/controls/import_records") self.browser.get(url) self.click_element(f"a.import_record_detail_link") self.click_element(f"a#delete-import") self.click_element(f"a#confirm-import-delete") var_sleep(1) current_path = urlparse(self.browser.current_url).path self.assertEqual('/controls/components', current_path) import_records_count = ImportRecord.objects.all().count() self.assertEqual(import_records_count, 0) component_count = Element.objects.filter(import_record=import_record).count() self.assertEqual(component_count, 0) statement_count = Statement.objects.filter(import_record=import_record).count() self.assertEqual(statement_count, 0) def test_element_rename(self): # Ensures that the edit button doesnt appear for non-superusers # Logs into a non-superuser account and goes to a components page self._login() url = self.url(f"controls/components/{self.component.id}") self.browser.get(url) # Asserts that the edit button element is not found on the page self.assertTrue(len(self.browser.find_elements_by_css_selector('#edit-button'))<1)