def test_system(self): login(self.browser) orig_date_modified = self.system.date_modified self.import_csv((u'csv_type,fqdn,location,arch\n' u'system,%s,Under my desk,ia64' % self.system.fqdn) .encode('utf8')) self.failUnless(is_text_present(self.browser, "No Errors")) with session.begin(): session.refresh(self.system) self.assertEquals(self.system.location, u'Under my desk') self.assert_(Arch.by_name(u'ia64') in self.system.arch) self.assert_(self.system.date_modified > orig_date_modified) # attempting to import a system with no FQDN should fail self.import_csv((u'csv_type,fqdn,location,arch\n' u'system,'',Under my desk,ia64').encode('utf8')) self.assertEquals(self.browser.find_element_by_xpath( '//table[@id="csv-import-log"]//td').text, "Error importing line 2: " "System must have an associated FQDN") # attempting to import a system with an invalid FQDN should fail self.import_csv((u'csv_type,fqdn,location,arch\n' u'system,invalid--fqdn,Under my desk,ia64').encode('utf8')) self.assertEquals(self.browser.find_element_by_xpath( '//table[@id="csv-import-log"]//td').text, "Error importing line 2: " "Invalid FQDN for system: invalid--fqdn")
def test_add_cc(self): with session.begin(): self.system.cc = [] b = self.browser login(b) self.go_to_system_view(tab='Owner') tab = b.find_element_by_id('owner') tab.find_element_by_name('cc').send_keys('*****@*****.**') tab.find_element_by_class_name('cc-add').submit() tab.find_element_by_xpath('.//li[contains(text(), "*****@*****.**")]') tab.find_element_by_name('cc').send_keys('*****@*****.**') tab.find_element_by_class_name('cc-add').submit() tab.find_element_by_xpath('.//li[contains(text(), "*****@*****.**")]') tab.find_element_by_xpath('.//li[contains(text(), "*****@*****.**")]') with session.begin(): session.refresh(self.system) self.assertEquals(set(self.system.cc), set([u'*****@*****.**', u'*****@*****.**'])) self.assertEquals(self.system.activity[0].field_name, u'Cc') self.assertEquals(self.system.activity[0].service, u'HTTP') self.assertEquals(self.system.activity[0].action, u'Added') self.assertEquals(self.system.activity[0].new_value, u'*****@*****.**') self.assertEquals(self.system.activity[1].field_name, u'Cc') self.assertEquals(self.system.activity[1].service, u'HTTP') self.assertEquals(self.system.activity[1].action, u'Added') self.assertEquals(self.system.activity[1].new_value, u'*****@*****.**')
def test_job_owner_can_change_retention_tag(self): with session.begin(): job_owner = data_setup.create_user(password=u'owner') job = data_setup.create_job(owner=job_owner, retention_tag=u'scratch') login(self.browser, user=job_owner.user_name, password=u'owner') self.check_can_change_retention_tag(job, '60days')
def test_useful_error_message_on_ksmeta_syntax_error(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with ksmeta syntax error</whiteboard> <recipeSet> <recipe ks_meta="'"> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() self.assertEquals(b.find_element_by_class_name('flash').text, 'Failed to import job because of: ' 'Error parsing ks_meta: No closing quotation')
def test_delete_install_options(self): with session.begin(): self.system.provisions[self.distro_tree.arch] = Provision( arch=self.distro_tree.arch, ks_meta=u'some_ks_meta_var=1', kernel_options=u'some_kernel_option=1', kernel_options_post=u'some_kernel_option=2') orig_date_modified = self.system.date_modified b = self.browser login(b) self.go_to_system_view(tab='Install Options') delete_and_confirm(b, '//tr[th/text()="Architecture"]') b.find_element_by_xpath('//h1[text()="%s"]' % self.system.fqdn) with session.begin(): session.refresh(self.system) self.assert_(self.system.date_modified > orig_date_modified) self.assert_(self.distro_tree.arch not in self.system.provisions) self.assertEquals(self.system.activity[0].action, u'Removed') self.assertEquals(self.system.activity[0].field_name, u'InstallOption:kernel_options_post:i386') self.assertEquals(self.system.activity[1].action, u'Removed') self.assertEquals(self.system.activity[1].field_name, u'InstallOption:kernel_options:i386') self.assertEquals(self.system.activity[2].action, u'Removed') self.assertEquals(self.system.activity[2].field_name, u'InstallOption:ks_meta:i386')
def test_update_labinfo(self): with session.begin(): # Due to bz987313 system must have existing lab info self.system.labinfo = LabInfo(weight=100) orig_date_modified = self.system.date_modified b = self.browser login(b) self.go_to_system_view(tab='Lab Info') changes = { 'orig_cost': '1,000.00', 'curr_cost': '500.00', 'dimensions': '1x1x1', 'weight': '50', 'wattage': '500', 'cooling': '1', } for k, v in changes.iteritems(): b.find_element_by_name(k).clear() b.find_element_by_name(k).send_keys(v) b.find_element_by_xpath('//button[text()="Save Lab Info Changes"]').click() self.assertEquals(b.find_element_by_class_name('flash').text, 'Saved Lab Info') for k, v in changes.iteritems(): self.assertEquals(b.find_element_by_name(k).get_attribute('value'), v) with session.begin(): session.refresh(self.system) self.assert_(self.system.date_modified > orig_date_modified)
def test_other_user_cannot_change_product(self): with session.begin(): other_user = data_setup.create_user(password=u'other_user') job = data_setup.create_job(retention_tag=u'active', product=data_setup.create_product()) login(self.browser, user=other_user.user_name, password=u'other_user') self.check_cannot_change_product(job)
def test_system_pools_import(self): with session.begin(): system = data_setup.create_system() pool1 = data_setup.create_system_pool() pool2 = data_setup.create_system_pool() login(self.browser) self.import_csv((u'csv_type,fqdn,pool,deleted\n' u'system_pool,%s,%s,False\n' u'system_pool,%s,%s,False'%(system.fqdn, pool1.name, system.fqdn, pool2.name)) \ .encode('utf8')) self.failUnless(is_text_present(self.browser, 'No Errors')) with session.begin(): session.refresh(system) self.assertEquals([pool1.name, pool2.name], [pool.name for pool in system.pools]) # test deletion self.import_csv((u'csv_type,fqdn,pool,deleted\n' u'system_pool,%s,%s,True' % (system.fqdn, pool2.name)) \ .encode('utf8')) self.failUnless(is_text_present(self.browser, 'No Errors')) with session.begin(): session.refresh(system) self.assertNotIn(pool2.name, [pool.name for pool in system.pools]) # Attempting to add a system to a Non existent pool should throw an error self.import_csv((u'csv_type,fqdn,pool,deleted\n' u'system_pool,%s,poolpool,True' % system.fqdn) \ .encode('utf8')) self.assertTrue(is_text_present(self.browser, 'poolpool: pool does not exist'))
def test_can_sort_activity_grid(self): with session.begin(): self.system.record_activity(service=u'testdata', field=u'status_reason', new=u'aaa') self.system.record_activity(service=u'testdata', field=u'status_reason', new=u'bbb') self.system.record_activity(service=u'testdata', field=u'status_reason', new=u'ccc') b = self.browser login(b) self.go_to_system_view(self.system, tab=u'Activity') tab = b.find_element_by_id('history') table = tab.find_element_by_tag_name('table') column = 7 # New Value # by default the grid is sorted by id descending cell_values = [table.find_element_by_xpath('tbody/tr[%d]/td[%d]' % (row, column)).text for row in [1, 2, 3]] self.assertEquals(cell_values, ['ccc', 'bbb', 'aaa']) # sort by New Value column table.find_element_by_xpath('thead/tr/th[%d]/a[text()="New Value"]' % column).click() # XXX need a loading indicator so we can wait for it time.sleep(2) cell_values = [table.find_element_by_xpath('tbody/tr[%d]/td[%d]' % (row, column)).text for row in [1, 2, 3]] self.assertEquals(cell_values, ['aaa', 'bbb', 'ccc'])
def test_duplicate_notify_cc_addresses_are_merged(self): with session.begin(): user = data_setup.create_user(password=u'hornet') b = self.browser login(b, user.user_name, u'hornet') b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with duplicate notify cc addresses</whiteboard> <notify> <cc>[email protected]</cc> <cc>[email protected]</cc> </notify> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() flash_message = b.find_element_by_class_name('flash').text self.assert_(flash_message.startswith('Success!'), flash_message) with session.begin(): job = Job.query.filter(Job.owner == user).order_by(Job.id.desc()).first() self.assertEqual(job.cc, ['*****@*****.**'])
def test_new_power_settings(self): with session.begin(): lc = data_setup.create_labcontroller() system = data_setup.create_system(lab_controller=lc, with_power=False) b = self.browser login(b) self.go_to_system_view(system=system, tab='Power Settings') tab = b.find_element_by_id('power-settings') BootstrapSelect(tab.find_element_by_name('power_type'))\ .select_by_visible_text('virsh') tab.find_element_by_name('power_address').send_keys \ ('qemu+ssh:10.10.10.10') tab.find_element_by_name('power_user').send_keys('root') tab.find_element_by_name('power_id').send_keys(system.fqdn) tab.find_element_by_tag_name('form').submit() # check activity records power_fields_changed = {'power_type': 'virsh', 'power_address': 'qemu+ssh:10.10.10.1', 'power_user': '******', 'power_id': system.fqdn, 'power_quiescent_period': 5} with session.begin(): session.refresh(system) for activity in system.activity: self.assertEquals(activity.new_value, power_fields_changed[activity])
def test_activity_is_not_logged_when_leaving_power_settings_empty(self): # The bug was that we were recording a change to power_user or # power_passwd because it changed from NULL to ''. with session.begin(): self.system.power.power_type = PowerType.lazy_create(name=u'ilo') self.system.power.power_user = None self.system.power.power_passwd = None self.system.power.power_id = None PowerType.lazy_create(name=u'drac') self.assertEquals(len(self.system.activity), 0) b = self.browser login(b) self.go_to_system_view(tab='Power Settings') tab = b.find_element_by_id('power-settings') # change power type but leave the other fields empty BootstrapSelect(tab.find_element_by_name('power_type'))\ .select_by_visible_text('drac') tab.find_element_by_tag_name('form').submit() tab.find_element_by_xpath('.//span[@class="sync-status" and not(text())]') with session.begin(): session.refresh(self.system) self.assertEquals(len(self.system.activity), 1, 'Expecting only one activity row for power_type but found: %r' % self.system.activity) self.assertEquals(self.system.activity[0].field_name, u'power_type')
def test_doesnt_barf_on_xml_encoding_declaration(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write('''<?xml version="1.0" encoding="utf-8"?> <job> <whiteboard>job with encoding in XML declaration яяя</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install" /> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() flash_message = b.find_element_by_class_name('flash').text self.assert_(flash_message.startswith('Success!'), flash_message)
def test_doesnt_barf_on_xmlns(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with namespace prefix declaration</whiteboard> <recipeSet> <recipe> <distroRequires xmlns:str="http://exslt.org/strings"> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() flash_message = b.find_element_by_class_name('flash').text self.assert_(flash_message.startswith('Success!'), flash_message)
def test_change_status(self): orig_date_modified = self.system.date_modified b = self.browser login(b) self.go_to_system_view(tab='Scheduler Settings') tab = b.find_element_by_id('scheduler-settings') BootstrapSelect(tab.find_element_by_name('status'))\ .select_by_visible_text('Broken') tab.find_element_by_xpath('.//button[text()="Save Changes"]').click() b.find_element_by_xpath('//span[@class="label label-warning"' ' and text()="Out of service"]') with session.begin(): session.refresh(self.system) self.assertEqual(self.system.status, SystemStatus.broken) self.assertEqual(len(self.system.status_durations), 2) self.assertEqual(self.system.status_durations[0].status, SystemStatus.broken) assertions.assert_datetime_within( self.system.status_durations[0].start_time, tolerance=datetime.timedelta(seconds=60), reference=datetime.datetime.utcnow()) self.assert_(self.system.status_durations[0].finish_time is None) self.assert_(self.system.status_durations[1].finish_time is not None) assertions.assert_durations_not_overlapping( self.system.status_durations) self.assert_(self.system.date_modified > orig_date_modified)
def test_add_group(self): with session.begin(): group = data_setup.create_group() user_password = '******' user = data_setup.create_user(password=user_password) data_setup.add_user_to_group(user, group) orig_date_modified = self.system.date_modified # as admin, assign the system to our test group b = self.browser login(b) self.go_to_system_view(tab='Groups') b.find_element_by_name('group.text').send_keys(group.group_name) b.find_element_by_name('groups').submit() b.find_element_by_xpath( '//div[@id="groups"]' '//td[normalize-space(text())="%s"]' % group.group_name) with session.begin(): session.refresh(self.system) self.assert_(self.system.date_modified > orig_date_modified) # as a user in the group, can we see it? logout(b) login(b, user.user_name, user_password) click_menu_item(b, 'Systems', 'Available') b.find_element_by_name('simplesearch').send_keys(self.system.fqdn) b.find_element_by_name('systemsearch_simple').submit() check_system_search_results(b, present=[self.system])
def test_job_with_excluded_task(self): with session.begin(): distro_tree = data_setup.create_distro_tree(arch=u'ia64') excluded_task = data_setup.create_task(exclude_arch=[u'ia64']) b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with excluded task</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="%s" /> <distro_arch op="=" value="ia64" /> </distroRequires> <hostRequires/> <task name="/distribution/install" role="STANDALONE"> <params/> </task> <task name="%s" role="STANDALONE"> <params/> </task> </recipe> </recipeSet> </job> ''' % (distro_tree.distro.name, excluded_task.name)) xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() flash_message = b.find_element_by_class_name('flash').text self.assert_(flash_message.startswith('Success!'), flash_message)
def test_missing_field(self): login(self.browser) orig_date_modified = self.system.date_modified self.import_csv((u'csv_type,fqdn,location,arch\n' u'system,%s,Under my desk' % self.system.fqdn) .encode('utf8')) self.assert_(is_text_present(self.browser, 'Missing fields on line 2: arch'))
def test_duplicate_packages_are_merged(self): b = self.browser login(b, user=self.user.user_name, password='******') b.get(get_server_base() + 'jobs/new') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with duplicate packages</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <packages> <package name="system-config-kdump"/> <package name="system-config-kdump"/> </packages> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_xpath("//input[@id='jobs_filexml']").send_keys(xml_file.name) b.find_element_by_xpath("//button[text()='Submit Data']").click() b.find_element_by_xpath("//button[text()='Queue']").click() flash_text = b.find_element_by_class_name('flash').text self.assert_('Success!' in flash_text, flash_text) self.assertEqual(b.title, 'My Jobs')
def test_extraneous_field(self): login(self.browser) orig_date_modified = self.system.date_modified self.import_csv((u'csv_type,fqdn,location,arch\n' u'system,%s,Under my desk,ppc64,what is this field doing here' % self.system.fqdn) .encode('utf8')) self.assert_(is_text_present(self.browser, 'Too many fields on line 2 (expecting 4)'))
def test_invalid_submission_delegate(self): with session.begin(): user = data_setup.create_user() invalid_delegate = data_setup.create_user(password='******') b = self.browser login(b, user=invalid_delegate.user_name, password='******') b.get(get_server_base() + 'jobs/new') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job user="******"> <whiteboard>job with submission delegate who is not allowed</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires> <system> <last_inventoried op=">" value="2010-10-10"/> </system> <system_type value="Machine"/> </hostRequires> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''' % user.user_name) xml_file.flush() b.find_element_by_xpath("//input[@id='jobs_filexml']").send_keys(xml_file.name) b.find_element_by_xpath("//button[text()='Submit Data']").click() b.find_element_by_xpath("//button[text()='Queue']").click() flash_text = b.find_element_by_class_name('flash').text self.assertEquals('Failed to import job because of: %s is not a valid' ' submission delegate for %s' % (invalid_delegate.user_name, user.user_name), flash_text, flash_text)
def test_invalid_inventory_date_with_not_equal(self): b = self.browser login(b, user=self.user.user_name, password='******') b.get(get_server_base() + 'jobs/new') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with invalid date value with equal op</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires> <system> <last_inventoried op="!=" value="2010-10-10 10:10:10"/> </system> <system_type value="Machine"/> </hostRequires> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_xpath("//input[@id='jobs_filexml']").send_keys(xml_file.name) b.find_element_by_xpath("//button[text()='Submit Data']").click() b.find_element_by_xpath("//button[text()='Queue']").click() b.find_element_by_xpath('//div[contains(@class, "alert")]' '/h4[contains(text(), "Job failed schema validation")]')
def test_valid_submission_delegate(self): with session.begin(): user = data_setup.create_user() submission_delegate = data_setup.create_user(password='******') user.submission_delegates[:] = [submission_delegate] b = self.browser login(b, user=submission_delegate.user_name, password='******') b.get(get_server_base() + 'jobs/new') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job user="******"> <whiteboard>job with submission delegate who is allowed</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires> <system_type value="Machine"/> </hostRequires> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''' % user.user_name) xml_file.flush() b.find_element_by_xpath("//input[@id='jobs_filexml']").send_keys(xml_file.name) b.find_element_by_xpath("//button[text()='Submit Data']").click() b.find_element_by_xpath("//button[text()='Queue']").click() flash_text = b.find_element_by_class_name('flash').text self.assert_('Success!' in flash_text, flash_text) self.assertEqual(b.title, 'My Jobs')
def test_partition_without_fs_doesnt_trigger_validation_warning(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with partition without fs</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <partitions> <partition name="/" size="4" type="part"/> </partitions> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() flash_message = b.find_element_by_class_name('flash').text self.assert_(flash_message.startswith('Success!'), flash_message)
def test_jobs_group_column(self): with session.begin(): user = data_setup.create_user(password='******') group1 = data_setup.create_group(owner=user) group2 = data_setup.create_group() user.groups.append(group2) job1 = data_setup.create_job(owner=user, group=None) job2 = data_setup.create_job(owner=user, group=group1) job3 = data_setup.create_job(owner=user, group=group2) b = self.browser # jobs/mine login(b, user=user.user_name, password='******') b.find_element_by_link_text('My Jobs').click() b.find_element_by_xpath('//title[normalize-space(text())="My Jobs"]') self.check_job_row(rownum=1, job_t_id=job3.t_id, group=group2) self.check_job_row(rownum=2, job_t_id=job2.t_id, group=group1) self.check_job_row(rownum=3, job_t_id=job1.t_id, group=None) # jobs logout(b) b.get(get_server_base() + 'jobs/') self.check_job_row(rownum=1, job_t_id=job3.t_id, group=group2) self.check_job_row(rownum=2, job_t_id=job2.t_id, group=group1) self.check_job_row(rownum=3, job_t_id=job1.t_id, group=None)
def test_warns_about_xsd_validation_errors(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with invalid hostRequires</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install" role="STANDALONE"> <params/> </task> <brokenElement/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() self.assertEqual(b.find_element_by_css_selector('.alert-error h4').text, 'Job failed schema validation. Please confirm that you want to submit it.') b.find_element_by_xpath('//ul[@class="xsd-error-list"]/li') b.find_element_by_xpath('//button[text()="Queue despite validation errors"]').click() b.find_element_by_xpath('//title[text()="My Jobs"]') flash_message = b.find_element_by_class_name('flash').text self.assert_(flash_message.startswith('Success!'), flash_message)
def test_invalid_email_addresses_are_not_accepted_in_notify_cc(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with invalid notify cc addresses</whiteboard> <notify> <cc>asdf</cc> </notify> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() flash_message = b.find_element_by_class_name('flash').text self.assertIn('Failed to import job', flash_message)
def test_xml_external_entities_are_rejected(self): b = self.browser login(b) b.get(get_server_base()) click_menu_item(b, 'Scheduler', 'New Job') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <job> <whiteboard>&xxe;</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires/> <task name="/distribution/install"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_id('jobs_filexml').send_keys(xml_file.name) b.find_element_by_xpath('//button[text()="Submit Data"]').click() b.find_element_by_xpath('//button[text()="Queue"]').click() self.assertEquals(b.find_element_by_class_name('flash').text, 'Failed to import job because of: ' 'XML entity with id file:///etc/passwd not permitted')
def test_update_system(self): orig_date_modified = self.system.date_modified b = self.browser login(b) self.go_to_system_view(tab='Details') tab = b.find_element_by_id('details') tab.find_element_by_xpath('.//button[contains(text(), "Edit")]').click() modal = b.find_element_by_class_name('modal') changes = { 'vendor': 'Sinclair', 'model': 'ZX80', 'serial_number': '12345', 'mac_address': 'aa:bb:cc:dd:ee:ff', } for k, v in changes.iteritems(): modal.find_element_by_name(k).clear() modal.find_element_by_name(k).send_keys(v) modal.find_element_by_xpath('.//button[text()="Save changes"]').click() tab.find_element_by_xpath('.//tr[th/text()="Vendor" and td/text()="Sinclair"]') tab.find_element_by_xpath('.//tr[th/text()="Model" and td/text()="ZX80"]') tab.find_element_by_xpath('.//tr[th/text()="Serial Number" and td/text()="12345"]') tab.find_element_by_xpath('.//tr[th/text()="MAC Address" and td/text()="aa:bb:cc:dd:ee:ff"]') with session.begin(): session.refresh(self.system) self.assert_(self.system.date_modified > orig_date_modified)
def test_valid_inventory_date(self): b = self.browser login(b, user=self.user.user_name, password='******') b.get(get_server_base() + 'jobs/new') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job> <whiteboard>job with invalid date value with equal op</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires> <system> <last_inventoried op=">" value="2010-10-10"/> </system> <system_type value="Machine"/> </hostRequires> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''') xml_file.flush() b.find_element_by_xpath("//input[@id='jobs_filexml']").send_keys(xml_file.name) b.find_element_by_xpath("//button[text()='Submit Data']").click() b.find_element_by_xpath("//button[text()='Queue']").click() flash_text = b.find_element_by_class_name('flash').text self.assert_('Success!' in flash_text, flash_text) self.assertEqual(b.title, 'My Jobs')
def test_record_ack_change(self): with session.begin(): owner = data_setup.create_user(password=u'owner') job = data_setup.create_job(owner=owner) data_setup.mark_job_complete(job, result=TaskResult.pass_) self.assertEquals(job.result, TaskResult.pass_) b = self.browser login(b, user=owner.user_name, password='******') b.get(get_server_base() + 'jobs/%s' % job.id) rs = b.find_element_by_xpath('//*[@id="RS_%s"]' % job.recipesets[0].id) rs.find_element_by_xpath( './/label[normalize-space(string(.))="Nak"]/input').click() rs.find_element_by_xpath('.//span[text()="Success"]') with session.begin(): self.assertEquals(job.recipesets[0].activity[0].service, u'WEBUI') self.assertEquals(job.recipesets[0].activity[0].field_name, 'Ack/Nak') self.assertEquals(job.recipesets[0].activity[0].object_name(), 'RecipeSet: %s' % job.recipesets[0].id) self.assertEquals(job.recipesets[0].activity[0].old_value, u'ack') self.assertEquals(job.recipesets[0].activity[0].new_value, u'nak')
def test_cannot_set_owner_to_invalid_user(self): b = self.browser login(b) self.go_to_system_view(tab='Owner') tab = b.find_element_by_id('owner') tab.find_element_by_xpath( './/button[contains(text(), "Change")]').click() modal = b.find_element_by_class_name('modal') modal.find_element_by_name('user_name').send_keys('$!7676') modal.find_element_by_tag_name('form').submit() self.assertIn('No such user', modal.find_element_by_class_name('alert-error').text) modal.find_element_by_xpath( './/button[contains(text(), "Save changes")]') # check errors don't stack up # https://bugzilla.redhat.com/show_bug.cgi?id=1161373 modal.find_element_by_tag_name('form').submit() modal.find_element_by_xpath( './/button[contains(text(), "Save changes")]') errors = modal.find_elements_by_class_name('alert-error') self.assertEquals(len(errors), 1, 'Multiple errors: %r' % errors)
def test_kernel_option_with_multiple_values(self): with session.begin(): user = data_setup.create_user(password=u'testing') system = data_setup.create_system(status=SystemStatus.manual, lab_controller=self.lc) system.provisions[self.distro_tree.arch] = \ Provision(arch=self.distro_tree.arch, kernel_options=u'key1=value1 key1=value2 key1 key2=value key3') system.reserve_manually(service=u'testdata', user=user) b = self.browser login(b, user=user.user_name, password='******') provision = self.go_to_provision_tab(system) self.select_distro_tree(self.distro_tree) provision.find_element_by_xpath( './/button[text()="Provision"]').click() b.find_element_by_xpath( './/div[contains(@class, "modal")]//button[text()="OK"]').click() b.find_element_by_xpath('//div[contains(@class, "alert-success")]' '/h4[text()="Provisioning successful"]') self.assert_(u'key1=value1 key1=value2 key2=value key3' in \ system.installations[0].kernel_options)
def test_add_rule_for_new_user(self): with session.begin(): data_setup.create_user(user_name=u'marple') b = self.browser login(b, user=self.system_owner.user_name, password='******') b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() # grant edit_policy permission to marple user pane = b.find_element_by_id('access-policy') pane.find_element_by_xpath('.//input[@placeholder="Username"]')\ .send_keys('marple\n') self.find_checkbox('marple', 'Edit this policy').click() self.check_row_is_dirty('marple') pane.find_element_by_xpath('.//button[text()="Save changes"]').click() self.check_row_is_not_dirty('marple') # refresh to check it has been persisted b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() self.assertTrue(self.find_checkbox('marple', 'Edit this policy').is_selected())
def test_doubled_quotes(self): with session.begin(): system = data_setup.create_system( fqdn=u'mymainframe.funtimes.invalid', arch=u's390x') OSMajor.lazy_create(osmajor=u'RedHatEnterpriseLinux7') b = self.browser login(b) b.get(get_server_base() + 'csv/csv_import') b.find_element_by_name('csv_file').send_keys( pkg_resources.resource_filename(self.__module__, 'bz802842.csv')) b.find_element_by_name('csv_file').submit() self.failUnless(is_text_present(self.browser, "No Errors")) with session.begin(): session.refresh(system) self.assertEquals(system.provisions[Arch.by_name(u's390x')]\ .provision_families[OSMajor.by_name(u'RedHatEnterpriseLinux7')]\ .kernel_options, 'rd.znet="qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=lol,portno=0" ' 'ip=1.2.3.4::1.2.3.4:255.255.248.0::eth0:none MTU=1500 nameserver=1.2.3.4 ' 'DASD=20A1,21A1,22A1,23A1 MACADDR=02:DE:AD:BE:EF:16 ' '!LAYER2 !DNS !PORTNO !IPADDR !GATEWAY !HOSTNAME !NETMASK ')
def test_cannot_return_running_recipe(self): with session.begin(): recipe = data_setup.create_recipe() data_setup.create_job_for_recipes([recipe]) data_setup.mark_recipe_running(recipe) system = recipe.resource.system b = self.browser login(b) b.get(get_server_base() + 'view/%s' % system.fqdn) # "Return" button should be absent b.find_element_by_xpath('//div[contains(@class, "system-quick-usage")' ' and not(.//a[text()="Return"])]') # try doing it directly s = requests.Session() requests_login(s) response = put_json(get_server_base() + 'systems/%s/reservations/+current' % system.fqdn, session=s, data=dict(finish_time='now')) self.assertEquals(response.status_code, 400) self.assertEquals(response.text, 'Currently running %s' % recipe.t_id)
def test_delete_undelete(self): b = self.browser login(b) b.get(get_server_base() + 'users/%s' % self.user.user_name) b.find_element_by_xpath('//button[contains(text(), "Delete")]').click() b.find_element_by_xpath( './/div[contains(@class, "modal")]//button[text()="OK"]').click() b.find_element_by_xpath( '//div[@class="alert" and contains(text(), "Account was removed")]' ) with session.begin(): session.expire_all() # Behaviour of user removal is exhaustively covered below in HTTP tests. self.assertIsNotNone(self.user.removed) b.find_element_by_xpath( '//button[contains(text(), "Undelete")]').click() # Wait for the button to change back to "Delete" b.find_element_by_xpath('//button[contains(text(), "Delete")]') with session.begin(): session.expire_all() self.assertIsNone(self.user.removed)
def test_cant_return_sneakily(self): with session.begin(): system = data_setup.create_system(shared=True, status=SystemStatus.manual) user = data_setup.create_user(password=u'password') b = self.browser login(b) #login as admin b.get(get_server_base() + 'view/%s' % system.fqdn) b.find_element_by_link_text('Take').click() b.find_element_by_xpath('//div[contains(@class, "system-quick-usage")]' '//span[@class="label" and text()="Reserved"]') # Test for https://bugzilla.redhat.com/show_bug.cgi?id=747328 s = requests.Session() requests_login(s, user.user_name, 'password') response = put_json(get_server_base() + 'systems/%s/reservations/+current' % system.fqdn, session=s, data=dict(finish_time='now')) self.assertEquals(response.status_code, 403) self.assertIn('cannot unreserve system', response.text)
def test_guestrecipes_appear_after_host(self): with session.begin(): user = data_setup.create_user(password=u'asdf') user.use_old_job_page = True # hack to force the GuestRecipe to be inserted first guest = data_setup.create_recipe(cls=GuestRecipe) job = data_setup.create_job_for_recipes([guest]) session.flush() host = data_setup.create_recipe() job.recipesets[0].recipes.append(host) host.guests.append(guest) session.flush() self.assert_(guest.id < host.id) b = self.browser login(b, user=user.user_name, password='******') b.get(get_server_base() + 'jobs/%s' % job.id) recipe_order = [ elem.text for elem in b.find_elements_by_xpath('//a[@class="recipe-id"]') ] self.assertEquals(recipe_order, [host.t_id, guest.t_id])
def test_remove_rule(self): b = self.browser login(b, user=self.system_owner.user_name, password='******') b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() # revoke loan_self permission from sidekicks group pane = b.find_element_by_id('access-policy') checkbox = find_policy_checkbox(b, 'sidekicks', 'Loan to self') self.assertTrue(checkbox.is_selected()) checkbox.click() check_policy_row_is_dirty(b, 'sidekicks') pane.find_element_by_xpath('.//button[text()="Save changes"]').click() pane.find_element_by_xpath('.//span[@class="sync-status" and not(node())]') # "sidekicks" row is completely absent now due to having no permissions check_policy_row_is_absent(b, 'sidekicks') # refresh to check it is persisted b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() pane = b.find_element_by_id('access-policy') self.assertNotIn('sidekicks', pane.text)
def test_job_activities_view(self): with session.begin(): job_owner = data_setup.create_user(password=u'owner') job_owner.use_old_job_page = True job = data_setup.create_job(owner=job_owner) job.record_activity(user=job_owner, service=u'test', field=u'test', action='change', old='old', new='new') login(self.browser, user=job_owner.user_name, password=u'owner') b = self.browser b.get(get_server_base() + 'jobs/%s' % job.id) b.find_element_by_link_text("Toggle Job history").click() activity_row = b.find_element_by_xpath( '//table[@id="job_history_datagrid"]/tbody/tr[1]') activity_row.find_element_by_xpath('./td[2][text()="%s"]' % u'test') activity_row.find_element_by_xpath('./td[4][text()="%s"]' % 'Job: %s' % job.id) activity_row.find_element_by_xpath('./td[6][text()="%s"]' % u'change')
def test_user_can_edit_their_own_details(self): b = self.browser login(b, user=self.user.user_name, password='******') b.get(get_server_base() + 'users/%s' % self.user.user_name) b.find_element_by_xpath( '//h1//button[contains(text(), "Edit")]').click() modal = b.find_element_by_class_name('modal') modal.find_element_by_name('display_name').clear() modal.find_element_by_name('display_name').send_keys('Bernie Sanders') modal.find_element_by_name('email_address').clear() modal.find_element_by_name('email_address').send_keys( '*****@*****.**') modal.find_element_by_tag_name('form').submit() b.find_element_by_xpath( '//body[not(.//div[contains(@class, "modal")])]') b.find_element_by_xpath('//h1/small[normalize-space(string(.))=' '"Bernie Sanders <*****@*****.**>"]') with session.begin(): session.expire_all() self.assertEqual(self.user.display_name, u'Bernie Sanders') self.assertEqual(self.user.email_address, u'*****@*****.**')
def test_edit_job_whiteboard(self): with session.begin(): user = data_setup.create_user(password=u'asdf') user.use_old_job_page = True job = data_setup.create_job(owner=user) b = self.browser login(b, user=user.user_name, password='******') b.get(get_server_base() + 'jobs/%s' % job.id) new_whiteboard = 'new whiteboard value %s' % int(time.time()) b.find_element_by_xpath( '//td[preceding-sibling::th[1]/text()="Whiteboard"]' '//a[text()="(Edit)"]').click() b.find_element_by_name('whiteboard').clear() b.find_element_by_name('whiteboard').send_keys(new_whiteboard) b.find_element_by_xpath('//form[@id="job_whiteboard_form"]' '//button[@type="submit"]').click() b.find_element_by_xpath( '//form[@id="job_whiteboard_form"]//div[@class="msg success"]') b.get(get_server_base() + 'jobs/%s' % job.id) b.find_element_by_xpath('//input[@name="whiteboard" and @value="%s"]' % new_whiteboard)
def test_provision_rejected_with_expired_root_password(self): with session.begin(): user = data_setup.create_user(password=u'testing') user.root_password = "******" user.rootpw_changed = datetime.datetime.utcnow( ) - datetime.timedelta(days=35) ConfigItem.by_name('root_password_validity').set( 30, user=User.by_user_name(data_setup.ADMIN_USER)) system = data_setup.create_system(status=SystemStatus.manual, lab_controller=self.lc) system.reserve_manually(service=u'testdata', user=user) b = self.browser login(b, user=user.user_name, password='******') provision = self.go_to_provision_tab(system) self.select_distro_tree(self.distro_tree) provision.find_element_by_xpath( './/button[text()="Provision"]').click() b.find_element_by_xpath( './/div[contains(@class, "modal")]//button[text()="OK"]').click() self.assertIn('root password has expired', provision.find_element_by_class_name('alert-error').text)
def test_return_with_no_lc(self): with session.begin(): lc = data_setup.create_labcontroller() system = data_setup.create_system(shared=True, status=SystemStatus.manual, lab_controller=lc) user = data_setup.create_user(password=u'password') b = self.browser login(b, user.user_name, 'password') b.get(get_server_base() + 'view/%s' % system.fqdn) b.find_element_by_link_text('Take').click() b.find_element_by_xpath('//div[contains(@class, "system-quick-usage")]' '//span[@class="label" and text()="Reserved"]') # Let's remove the LC with session.begin(): system.lc = None b.get(get_server_base() + 'view/%s' % system.fqdn) b.find_element_by_link_text('Return').click() b.find_element_by_xpath('//div[contains(@class, "system-quick-usage")]' '//span[@class="label" and text()="Idle"]')
def test_can_remove_tag_from_distro(self): b = self.browser login(b, data_setup.ADMIN_USER, data_setup.ADMIN_PASSWORD) go_to_distro_view(b, self.distro) delete_and_confirm( b, '//td[normalize-space(preceding-sibling::td[1]/text())="SAD"]') self.assertEquals( b.find_element_by_class_name('flash').text, 'Removed Tag SAD') b.find_element_by_xpath('//div[@class="tags"]//table[not(' './/td[normalize-space(text())="SAD"])]') with session.begin(): session.refresh(self.distro) self.assert_(u'SAD' not in self.distro.tags) with session.begin(): session.refresh(self.distro) activity = self.distro.activity[0] self.assertEquals(activity.field_name, u'Tag') self.assertEquals(activity.service, u'WEBUI') self.assertEquals(activity.action, u'Removed') self.assertEquals(activity.old_value, u'SAD') self.assertEquals(activity.new_value, None)
def test_remove_group(self): with session.begin(): group = data_setup.create_group() self.system.groups.append(group) orig_date_modified = self.system.date_modified b = self.browser login(b) self.go_to_system_view(tab='Groups') b.find_element_by_xpath('//td[normalize-space(text())="%s"]' % group.group_name) delete_and_confirm( b, '//tr[normalize-space(td[1]/text())="%s"]' % group.group_name) self.assertEquals( b.find_element_by_class_name('flash').text, '%s Removed' % group.display_name) b.find_element_by_xpath( '//div[@id="groups" and not(.//td[normalize-space(text())="%s"])]' % group.group_name) with session.begin(): session.refresh(self.system) self.assert_(self.system.date_modified > orig_date_modified)
def test_give_away_permission(self): with session.begin(): user = data_setup.create_user(password='******') owner = data_setup.create_user(password='******') system = data_setup.create_system(owner=owner) pool = data_setup.create_system_pool(systems=[system]) pool.access_policy.add_rule( user=user, permission=SystemPermission.edit_policy) system.active_access_policy = pool.access_policy b = self.browser login(b, user=user.user_name, password='******') b.get(get_server_base() + 'view/%s/' % system.fqdn) b.find_element_by_link_text('Access Policy').click() pane = b.find_element_by_id('access-policy') # Currently the system is using a pool access policy self.assertTrue( pane.find_element_by_xpath( '//label[contains(string(.), "Use policy from pool:")]' '/input[@type="radio"]').is_selected()) # change to custom access policy pane.find_element_by_xpath( '//label[contains(string(.), "Use custom access policy")]' '/input[@type="radio"]').click() pane.find_element_by_xpath('.//button[text()="Save changes"]').click() pane.find_element_by_xpath( '//div[@id="access-policy" and not (.//div[@class="form-actions"])]' ) self.assertTrue( pane.find_element_by_xpath( '//label[contains(string(.), "Use custom access policy")]' '/input[@type="radio"]').is_selected()) # The radio buttons should be read only self.assertFalse( b.find_element_by_xpath( '//label[contains(string(.), "Use policy from pool:")]' '/input[@type="radio"]').is_enabled()) self.assertFalse( b.find_element_by_xpath( '//label[contains(string(.), "Use custom access policy")]' '/input[@type="radio"]').is_enabled())
def test_submission_delegate_cancel_job(self): with session.begin(): submission_delegate = data_setup.create_user(password='******') self.user.submission_delegates[:] = [submission_delegate] b = self.browser login(b, submission_delegate.user_name, password='******') b.get(get_server_base() + 'jobs') b.find_element_by_link_text("Show Search Options").click() wait_for_animation(b, '#searchform') Select(b.find_element_by_name('jobsearch-0.table'))\ .select_by_visible_text('Id') Select(b.find_element_by_name('jobsearch-0.operation'))\ .select_by_visible_text('is') b.find_element_by_name('jobsearch-0.value').clear() b.find_element_by_name('jobsearch-0.value'). \ send_keys('%s' % self.job.id) b.find_element_by_id('searchform').submit() # We are only a submission delegate, but not the submitter, # check we cannot Cancel action_text = b.find_element_by_xpath( "//td[preceding-sibling::td/" "a[normalize-space(text())='%s']]/" "div[contains(@class, 'job-action-container')]" % self.job.t_id).text self.assertTrue('Cancel' not in action_text) # Add as submitting user and refresh, try to cancel. with session.begin(): self.job.submitter = submission_delegate b.refresh() b.find_element_by_xpath("//td[preceding-sibling::td/" "a[normalize-space(text())='%s']]/div//" "a[normalize-space(text())='Cancel']" % self.job.t_id).click() b.find_element_by_xpath( "//input[@class='submitbutton' and @value='Yes']").click() self.assertEquals( b.find_element_by_class_name('flash').text, 'Successfully cancelled job %s' % self.job.id)
def test_nacked_recipe_results_not_shown(self): with session.begin(): data_setup.create_completed_job( whiteboard=self.job_whiteboard, result=TaskResult.fail, recipe_whiteboard=self.recipe_whiteboard) data_setup.create_completed_job( whiteboard=self.job_whiteboard, result=TaskResult.warn, recipe_whiteboard=self.recipe_whiteboard) owner = data_setup.create_user(password='******') self.passed_job.owner = owner b = self.browser login(b, user=owner.user_name, password='******') b.get(get_server_base() + 'matrix') b.find_element_by_xpath( "//select[@name='whiteboard']/option[@value='%s']" % self.job_whiteboard).click() b.find_element_by_xpath("//input[@name='toggle_nacks_on']").click() b.find_element_by_xpath( '//button[@type="submit" and text()="Generate"]').click() report_text = b.find_element_by_xpath( "//div[@id='matrix-report']").text self.assert_('Pass: 1' in report_text) # Nack Recipe with session.begin(): self.passed_job.recipesets[0].waived = True # Assert it is no longer there b.get(get_server_base() + 'matrix') b.find_element_by_xpath( "//select[@name='whiteboard']/option[@value='%s']" % self.job_whiteboard).click() b.find_element_by_xpath("//input[@name='toggle_nacks_on']").click() b.find_element_by_xpath( '//button[@type="submit" and text()="Generate"]').click() report_text = b.find_element_by_xpath( "//div[@id='matrix-report']").text self.assert_('Pass: 1' not in report_text)
def test_can_reserve_manual_system(self): with session.begin(): broken_system = data_setup.create_system( arch=u'i386', shared=True, status=SystemStatus.broken, lab_controller=self.lc) manual_system = data_setup.create_system( arch=u'i386', shared=True, status=SystemStatus.manual, lab_controller=self.lc) b = self.browser login(b) # broken system should not be present go_to_reserve_systems(b, distro_tree=self.distro_tree_i386) search_for_system(b, broken_system) check_system_search_results(b, absent=[broken_system]) # provision manual system go_to_reserve_systems(b, distro_tree=self.distro_tree_i386) search_for_system(b, manual_system) row = b.find_element_by_xpath( '//tr[normalize-space(string(td))="%s"]' % manual_system.fqdn) row.find_element_by_link_text('Reserve Now').click() b.find_element_by_xpath( '//button[normalize-space(text())="Submit job"]').click() # should end up on the job page job_id = b.find_element_by_xpath('//h1//span[@class="job-id"]').text wb_descr = (WORKFLOW_DESCR % ("None", "a specific system", "86400")) wboard = b.find_element_by_class_name('job-whiteboard') self.assertIn(wb_descr, wboard.text, msg="Fail to match default whiteboard") with session.begin(): job = TaskBase.get_by_t_id(job_id) cloned_job_xml = lxml.etree.tostring( job.to_xml(clone=True), encoding=unicode) # cloning re-parses hostRequires self.assertIn(u'<hostRequires force="%s"/>' % manual_system.fqdn, cloned_job_xml)
def test_action_buttons(self): """ Check that the right action buttons appear in the right circumstances. """ with session.begin(): user = data_setup.create_user(password=u'asdflol') no_access = data_setup.create_system(shared=False) borrowable = data_setup.create_system() borrowable.custom_access_policy.add_rule( SystemPermission.loan_self, user=user) borrowable_but_loaned = data_setup.create_system() borrowable_but_loaned.loaned = data_setup.create_user() borrowable_but_loaned.custom_access_policy.add_rule( SystemPermission.loan_self, user=user) borrowed = data_setup.create_system() borrowed.loaned = user # "stealable" means loaned to someone else but you have perms to return their loan stealable = data_setup.create_system() stealable.loaned = data_setup.create_user() stealable.custom_access_policy.add_rule(SystemPermission.loan_any, user=user) manual = data_setup.create_system(status=SystemStatus.manual, shared=True) taken = data_setup.create_system(status=SystemStatus.manual, shared=True) taken.reserve_manually(user=user, service=u'testdata') login(self.browser, user=user.user_name, password='******') self.go_to_system_view(no_access) self.assertEquals(self.action_button_labels(), ['Request Loan']) self.go_to_system_view(borrowable_but_loaned) self.assertEquals(self.action_button_labels(), ['Schedule Reservation']) self.go_to_system_view(borrowable) self.assertEquals(self.action_button_labels(), ['Borrow']) self.go_to_system_view(borrowed) self.assertEquals(self.action_button_labels(), ['Take', 'Return Loan']) self.go_to_system_view(stealable) self.assertEquals(self.action_button_labels(), ['Return Loan']) self.go_to_system_view(manual) self.assertEquals(self.action_button_labels(), ['Take']) self.go_to_system_view(taken) self.assertEquals(self.action_button_labels(), ['Return'])
def test_cannot_update_with_empty_name(self): """Verifies that the pool cannot be updated with an empty name.""" self.assertTrue(self.pool.name, "Cannot run test with empty pool name in fixture") b = self.browser login(b) self.go_to_pool_edit(system_pool=self.pool) b.find_element_by_xpath('.//button[contains(text(), "Edit")]').click() modal = b.find_element_by_class_name('modal') modal.find_element_by_name('name').clear() modal.find_element_by_xpath('.//button[text()="Save changes"]').click() self.assertTrue( modal.find_element_by_css_selector( 'input[name="name"]:required:invalid')) # verify that the pool's name is not modified and the name not empty due # to the validation error with session.begin(): session.refresh(self.pool) self.assertTrue(self.pool.name)
def test_invalid_submission_delegate(self): with session.begin(): user = data_setup.create_user() invalid_delegate = data_setup.create_user(password='******') b = self.browser login(b, user=invalid_delegate.user_name, password='******') b.get(get_server_base() + 'jobs/new') xml_file = tempfile.NamedTemporaryFile() xml_file.write(''' <job user="******"> <whiteboard>job with submission delegate who is not allowed</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> </distroRequires> <hostRequires> <system> <last_inventoried op=">" value="2010-10-10"/> </system> <system_type value="Machine"/> </hostRequires> <task name="/distribution/install" role="STANDALONE"/> </recipe> </recipeSet> </job> ''' % user.user_name) xml_file.flush() b.find_element_by_xpath("//input[@id='jobs_filexml']").send_keys( xml_file.name) b.find_element_by_xpath("//button[text()='Submit Data']").click() b.find_element_by_xpath("//button[text()='Queue']").click() flash_text = b.find_element_by_class_name('flash').text self.assertEquals( 'Failed to import job because of: %s is not a valid' ' submission delegate for %s' % (invalid_delegate.user_name, user.user_name), flash_text, flash_text)
def test_group_not_in_cache(self): b = self.browser login(b, user=self.system_owner.user_name, password='******') b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() pane = b.find_element_by_id('access-policy') # type the group name before it exists with session.begin(): self.assertEquals(Group.query.filter_by(group_name=u'beatles').first(), None) group_input = pane.find_element_by_xpath('.//input[@placeholder="Group name"]') group_input.send_keys('beatles') # group is created with session.begin(): data_setup.create_group(group_name=u'beatles') # type it again group_input.clear() group_input.send_keys('beatles') # suggestion should appear pane.find_element_by_xpath('.//div[@class="tt-suggestion" and ' 'contains(string(.), "beatles")]') group_input.send_keys('\n') find_policy_checkbox(b, 'beatles', 'Edit this policy')
def test_remove_self_edit_policy_permission(self): b = self.browser login(b, user=self.system_owner.user_name, password='******') b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() pane = b.find_element_by_id('access-policy') # grant poirot edit_policy permission find_policy_checkbox(b, 'poirot', 'Edit this policy').click() pane.find_element_by_xpath('.//button[text()="Save changes"]').click() pane.find_element_by_xpath('.//span[@class="sync-status" and not(node())]') logout(b) login(b, user='******', password='******') b.get(get_server_base() + 'view/%s/' % self.system.fqdn) b.find_element_by_link_text('Access Policy').click() pane = b.find_element_by_id('access-policy') # remove self edit_policy permission find_policy_checkbox(b, 'poirot', 'Edit this policy').click() pane.find_element_by_xpath('.//button[text()="Save changes"]').click() # the widget should be readonly pane.find_element_by_xpath('.//table[not(.//input[@type="checkbox" and not(@disabled)])]') pane.find_element_by_xpath('.//table[not(.//input[@type="text"])]')
def test_system_secret_field(self): login(self.browser) self.import_csv((u'csv_type,fqdn,secret\n' u'system,%s,True' % self.system.fqdn).encode('utf8')) self.assertEquals( self.browser.find_element_by_xpath( '//table[@id="csv-import-log"]//td').text, 'No Errors') with session.begin(): session.refresh(self.system.custom_access_policy) self.assertFalse( self.system.custom_access_policy.grants_everybody( SystemPermission.view)) self.import_csv((u'csv_type,fqdn,secret\n' u'system,%s,False' % self.system.fqdn).encode('utf8')) self.assertEquals( self.browser.find_element_by_xpath( '//table[@id="csv-import-log"]//td').text, 'No Errors') with session.begin(): session.refresh(self.system.custom_access_policy) self.assertTrue( self.system.custom_access_policy.grants_everybody( SystemPermission.view))
def test_add_bad_permission(self): b = self.browser login(b) b.get(get_server_base() + 'groups/edit?group_id=%d' % self.group.group_id) b.find_element_by_id('Permissions_permissions_text').send_keys( 'dummy_perm') b.find_element_by_id('Permissions').submit() #Test that it has not been dynamically added b.find_element_by_xpath( '//span[@id="response_Permissions_failure" and ' 'text()="Invalid permission value"]') #Double check that it wasn't added to the permissions b.find_element_by_xpath('//table[@id="group_permission_grid" and ' 'not(.//td/text()="dummy_perm")]') #Triple check it was not persisted to the DB b.get(get_server_base() + 'groups/edit?group_id=%d' % self.group.group_id) b.find_element_by_xpath('//table[@id="group_permission_grid" and ' 'not(.//td/text()="dummy_perm")]')
def test_password_visibility_members(self): b = self.browser login(b, user=self.user.user_name, password='******') self._make_and_go_to_owner_page(self.user, self.group) e = b.find_element_by_xpath('//input[@id="Group_root_password"]') e.clear() e.send_keys(self.clear_password) b.find_element_by_id('Group').submit() self.assertEquals(b.find_element_by_class_name('flash').text, u'OK') logout(b) # add a new user as a group member with session.begin(): user = data_setup.create_user(password='******') user.groups.append(self.group) # login as the new user login(b, user=user.user_name, password='******') b.get(get_server_base() + 'groups/mine') b.find_element_by_link_text(self.group.group_name).click() self.assertEquals( b.find_element_by_xpath("//div[@id='root_pw_display']/p").text, "The group root password is: %s" % self.clear_password)
def test_task_result_datetimes_are_localised(self): with session.begin(): user = data_setup.create_user(password=u'asdf') user.use_old_job_page = True job = data_setup.create_completed_job() b = self.browser login(b, user=user.user_name, password='******') b.get(get_server_base() + 'jobs/%s' % job.id) recipe_id = job.recipesets[0].recipes[0].id b.find_element_by_xpath( '//div[@id="recipe%s"]//a[text()="Show Results"]' % recipe_id).click() b.find_element_by_xpath( '//div[@id="recipe-%d-results"]//table' % recipe_id) recipe_task_start, recipe_task_finish, recipe_task_duration = \ b.find_elements_by_xpath( '//div[@id="recipe-%d-results"]//table' '/tbody/tr[1]/td[3]/div' % recipe_id) self.check_datetime_localised(recipe_task_start.text.strip()) self.check_datetime_localised(recipe_task_finish.text.strip()) self.check_datetime_localised(b.find_element_by_xpath( '//div[@id="recipe-%d-results"]//table' '/tbody/tr[2]/td[3]' % recipe_id).text)