address #73 #80
address #73 #80
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,30 +9,186 @@ | |
from selenium.webdriver.common.by import By | ||
from selenium.webdriver.support.select import Select | ||
|
||
from pages.page import Page | ||
from pages.base_page import MozTrapBasePage | ||
|
||
|
||
class MozTrapCreateRunPage(MozTrapBasePage): | ||
|
||
_page_title = 'MozTrap' | ||
|
||
class MozTrapEditRunPage(MozTrapBasePage): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. expected 2 blank lines, found 1 |
||
_known_kwargs = ['name', 'desc', 'start_date', 'end_date', 'suite_list'] | ||
_product_version_readonly_locator = (By.CSS_SELECTOR, 'div.formfield.product-version-field.readonly > span') | ||
_name_locator = (By.ID, 'id_name') | ||
_product_version_select_locator = (By.ID, 'id_productversion') | ||
_description_locator = (By.ID, 'id_description') | ||
_start_date_locator = (By.ID, 'id_start') | ||
_end_date_locator = (By.ID, 'id_end') | ||
_suite_select_locator = (By.CSS_SELECTOR, '#run-add-form .multiunselected .itemlist article.selectitem[data-title="%(suite_name)s"] input.bulk-value') | ||
_include_selected_suites_locator = (By.CSS_SELECTOR, '#run-add-form .multiselect .include-exclude .action-include') | ||
_available_suites_locator = (By.CSS_SELECTOR, '.multiunselected .itemlist article.selectitem') | ||
_included_suites_locator = (By.CSS_SELECTOR, '.multiselected .itemlist article.selectitem') | ||
_include_selected_suites_locator = (By.CSS_SELECTOR, '.multiselect .include-exclude .action-include') | ||
_remove_selected_suites_locator = (By.CSS_SELECTOR, '.multiselect .include-exclude .action-exclude') | ||
_submit_locator = (By.CSS_SELECTOR, '#run-add-form .form-actions > button') | ||
|
||
# Note on __init__: it fails with 'ReferenceError: jQuery is not defined' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incidentally a dev for Socorro recently updated this method in socorro-tests to check for jQuery's existence and that .active == 0 to work around problems where on pages where jQuery might not exist. |
||
# if you try to wait_for_ajax | ||
|
||
def fill_fields(self, **kwargs): | ||
''' | ||
::keyword args:: | ||
name | ||
desc | ||
start_date | ||
end_date | ||
suite_list | ||
''' | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blank line contains whitespace |
||
for key in kwargs.keys(): | ||
if not key in self._known_kwargs: | ||
raise Exception("%s unrecognized, use only recognized kwargs:\n%s" % | ||
(key, "\n".join(self._known_kwargs))) | ||
|
||
if kwargs.has_key('name'): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. .has_key() is deprecated, use 'in' |
||
name_field = self.selenium.find_element(*self._name_locator) | ||
name_field.send_keys(kwargs['name']) | ||
if kwargs.has_key('desc'): | ||
self.selenium.find_element(*self._description_locator).send_keys(kwargs['desc']) | ||
if kwargs.has_key('start_date'): | ||
self.type_in_element(self._start_date_locator, kwargs['start_date']) | ||
if kwargs.has_key('end_date'): | ||
self.selenium.find_element(*self._end_date_locator).send_keys(kwargs['end_date']) | ||
|
||
if kwargs.has_key('suite_list') and kwargs['suite_list']: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i am trying to decide if this section is overly complicated (remove unwanted from include, add wanted from available, check to make sure there are no wanteds that aren't available). none of the tests actually test the removal of suites from runs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I agree it's probably not safe to assume that suites should be deselected if they're not in the included list. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An API for inserting test data would be so beneficial for this project! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can has feature request =) |
||
# remove unwanted | ||
for suite in self.included_suites: | ||
print 'included has %s' % suite.name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should delete this print and the ones below. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think i've moved most of the prints, but i left one that was very very useful in debugging. |
||
if not suite.name in kwargs['suite_list']: | ||
print 'selecting for removal' | ||
suite.select() | ||
self.remove_selected_suites() | ||
# add wanted | ||
for suite in self.available_suites: | ||
print 'available has %s' % suite.name | ||
if suite.name in kwargs['suite_list']: | ||
print 'selecting for addition' | ||
suite.select() | ||
self.add_selected_suites() | ||
# check for strays | ||
included_suite_names = self.included_suite_names | ||
for suite_name in kwargs['suite_list']: | ||
if not suite_name in included_suite_names: | ||
raise Exception('suite %s not found' % suite_name) | ||
|
||
self.selenium.find_element(*self._submit_locator).click() | ||
|
||
@property | ||
def product_version(self): | ||
return self.selenium.find_element(*self._product_version_readonly_locator).text | ||
|
||
@property | ||
def included_suites(self): | ||
'''this method only works if run is in draft mode.''' | ||
suites = self.selenium.find_elements(*self._included_suites_locator) | ||
included_suites = [self.Suite(self.testsetup, loc) for loc in suites] | ||
print 'included_suites:\n%s' % included_suites | ||
return included_suites | ||
|
||
@property | ||
def included_suite_names(self): | ||
# XXX fix this so that it returns something when run is active | ||
included_suite_names = [suite.name for suite in self.included_suites] | ||
print 'included_suite_names:\n%s' % included_suite_names | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should remove this print. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hi @teodosia |
||
return included_suite_names | ||
|
||
def remove_selected_suites(self): | ||
'''this method only works if run is in draft mode.''' | ||
self.selenium.find_element(*self._remove_selected_suites_locator).click() | ||
|
||
@property | ||
def available_suites(self): | ||
'''this method only works if run is in draft mode.''' | ||
suites = self.selenium.find_elements(*self._available_suites_locator) | ||
return [self.Suite(self.testsetup, loc) for loc in suites] | ||
|
||
@property | ||
def available_suite_names(self): | ||
'''this method only works if run is in draft mode.''' | ||
return [suite.name for suite in self.available_suites] | ||
|
||
def add_selected_suites(self): | ||
'''this method only works if run is in draft mode.''' | ||
self.selenium.find_element(*self._include_selected_suites_locator).click() | ||
|
||
class Suite(Page): | ||
_name_locator = (By.CSS_SELECTOR, 'div.name > h5.title') | ||
_checkbox_locator = (By.CSS_SELECTOR, 'label.bulk-type') | ||
_drag_locator = (By.CSS_SELECTOR, ) | ||
|
||
def __init__(self, testsetup, webelement): | ||
Page.__init__(self, testsetup) | ||
self.webelement = webelement | ||
|
||
@property | ||
def name(self): | ||
return self.webelement.find_element(*self._name_locator).text | ||
|
||
@property | ||
def position(self): | ||
pass | ||
|
||
def select(self): | ||
self.webelement.find_element(*self._checkbox_locator).click() | ||
|
||
def drag_to(self, position): | ||
pass | ||
|
||
|
||
class MozTrapCreateRunPage(MozTrapEditRunPage): | ||
|
||
_page_title = 'MozTrap' | ||
|
||
_product_version_select_locator = (By.ID, 'id_productversion') | ||
_run_manage_locator = (By.CSS_SELECTOR, '#manageruns .itemlist .listitem .title[title="%(run_name)s"]') | ||
_run_homepage_locator = (By.CSS_SELECTOR, '.runsdrill .runsfinder .runs .colcontent .title[title="%(run_name)s"]') | ||
_run_tests_button_locator = (By.CSS_SELECTOR, 'div.form-actions > button') | ||
|
||
def __init__(self, testsetup): | ||
MozTrapEditRunPage.__init__(self, testsetup) | ||
self._known_kwargs.append('product_version') | ||
|
||
def go_to_create_run_page(self): | ||
self.selenium.get(self.base_url + '/manage/run/add/') | ||
self.is_the_current_page | ||
|
||
def create_run(self, name='Test Run', product_version='Test Product Test Version', desc='This is a test run', start_date='2011-01-01', end_date='2012-12-31', suite_list=None): | ||
def fill_fields(self, **kwargs): | ||
''' | ||
::keyword args:: | ||
name | ||
product_version | ||
desc | ||
start_date | ||
end_date | ||
suite_list | ||
''' | ||
|
||
if kwargs.has_key('product_version'): | ||
product_version_select = Select(self.selenium.find_element(*self._product_version_select_locator)) | ||
product_version_select.select_by_visible_text(kwargs['product_version']) | ||
|
||
MozTrapEditRunPage.fill_fields(self, **kwargs) | ||
|
||
|
||
def create_run(self, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. trailing whitespace & too many blank lines |
||
name='Test Run', | ||
product_version='Test Product Test Version', | ||
desc='This is a test run', | ||
start_date='2011-01-01', | ||
end_date='2012-12-31', | ||
suite_list=None): | ||
''' | ||
::keyword args:: | ||
name | ||
product_version | ||
desc | ||
start_date | ||
end_date | ||
suite_list | ||
''' | ||
dt_string = datetime.utcnow().isoformat() | ||
run = {} | ||
run['name'] = u'%(name)s %(dt_string)s' % {'name': name, 'dt_string': dt_string} | ||
|
@@ -41,23 +197,12 @@ def create_run(self, name='Test Run', product_version='Test Product Test Version | |
run['homepage_locator'] = (self._run_homepage_locator[0], self._run_homepage_locator[1] % {'run_name': run['name']}) | ||
run['run_tests_locator'] = self._run_tests_button_locator | ||
|
||
name_field = self.selenium.find_element(*self._name_locator) | ||
name_field.send_keys(run['name']) | ||
|
||
product_version_select = Select(self.selenium.find_element(*self._product_version_select_locator)) | ||
product_version_select.select_by_visible_text(product_version) | ||
|
||
self.selenium.find_element(*self._description_locator).send_keys(run['desc']) | ||
|
||
self.type_in_element(self._start_date_locator, start_date) | ||
self.selenium.find_element(*self._end_date_locator).send_keys(end_date) | ||
|
||
if suite_list: | ||
|
||
for suite in suite_list: | ||
suite_input_element = self.selenium.find_element(By.XPATH, "//article[@data-title='%s']//label" % suite) | ||
suite_input_element.click() | ||
self.selenium.find_element(*self._include_selected_suites_locator).click() | ||
self.selenium.find_element(*self._submit_locator).click() | ||
self.fill_fields( | ||
name=run['name'], | ||
product_version=product_version, | ||
desc=run['desc'], | ||
start_date=start_date, | ||
end_date=end_date, | ||
suite_list=suite_list) | ||
|
||
return run |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,30 +6,24 @@ | |
|
||
from selenium.webdriver.common.by import By | ||
|
||
from pages.page import Page | ||
from pages.base_page import MozTrapBasePage | ||
from pages.create_run_page import MozTrapEditRunPage | ||
|
||
|
||
class MozTrapManageRunsPage(MozTrapBasePage): | ||
|
||
_page_title = 'MozTrap' | ||
|
||
_delete_run_locator = (By.CSS_SELECTOR, '#manageruns .itemlist .listitem[data-title="%(run_name)s"] .action-delete') | ||
_run_activate_locator = (By.CSS_SELECTOR, '#manageruns .itemlist .listitem[data-title="%(run_name)s"] .status-action.active') | ||
_run_status_locator = (By.CSS_SELECTOR, '#manageruns .itemlist .listitem[data-title="%(run_name)s"] .status-title') | ||
_filter_input_locator = (By.ID, 'text-filter') | ||
_filter_suggestion_locator = (By.CSS_SELECTOR, '#filter .textual .suggest .suggestion[data-type="name"][data-name="%(filter_name)s"]') | ||
_filter_locator = (By.CSS_SELECTOR, '#filterform .filter-group input[data-name="name"][value="%(filter_name)s"]:checked') | ||
_run_item_locator = (By.CSS_SELECTOR, '#manageruns .itemlist .listitem') | ||
|
||
def go_to_manage_runs_page(self): | ||
self.selenium.get(self.base_url + '/manage/runs/') | ||
self.is_the_current_page | ||
|
||
def delete_run(self, name='Test Run'): | ||
_delete_locator = (self._delete_run_locator[0], self._delete_run_locator[1] % {'run_name': name}) | ||
|
||
self.selenium.find_element(*_delete_locator).click() | ||
self.wait_for_ajax() | ||
|
||
def filter_runs_by_name(self, name): | ||
_filter_suggestion_locator = (self._filter_suggestion_locator[0], self._filter_suggestion_locator[1] % {'filter_name': name}) | ||
|
||
|
@@ -43,11 +37,30 @@ def remove_name_filter(self, name): | |
self.selenium.find_element(*self._filter_locator).click() | ||
self.wait_for_ajax() | ||
|
||
def activate_run(self, name='Test Run'): | ||
_run_activate_locator = (self._run_activate_locator[0], self._run_activate_locator[1] % {'run_name': name}) | ||
_run_status_locator = (self._run_status_locator[0], self._run_status_locator[1] % {'run_name': name}) | ||
|
||
self.selenium.find_element(*_run_status_locator).click() | ||
self.selenium.find_element(*_run_activate_locator).click() | ||
|
||
self.wait_for_ajax() | ||
@property | ||
def get_runs(self): | ||
runs = self.selenium.find_elements(*self._run_item_locator) | ||
return [self.Run(self.testsetup, run) for run in runs] | ||
|
||
class Run(Page): | ||
_delete_run_locator = (By.CSS_SELECTOR, '.action-delete') | ||
_run_activate_locator = (By.CSS_SELECTOR, '.status-action.active') | ||
_run_status_locator = (By.CSS_SELECTOR, '.status-title') | ||
_edit_run_locator = (By.CSS_SELECTOR, 'a.edit-link') | ||
|
||
def __init__(self, testsetup, webelement): | ||
Page.__init__(self, testsetup) | ||
self.webelement = webelement | ||
|
||
def delete(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These would be better as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. after seeing how many times i have to filter the runs by name, get the list of one run, and do something to it, i am thinking that the manage page needs delete_run(name), activate_run(name) and edit_run(name) after all. that being said, i still think Runs should be sub-objects rather than having to wiggle the locators each time. |
||
self.webelement.find_element(*self._delete_run_locator).click() | ||
self.wait_for_ajax() | ||
|
||
def edit(self): | ||
self.webelement.find_element(*self._edit_run_locator).click() | ||
return MozTrapEditRunPage(self.testsetup) | ||
|
||
def activate(self): | ||
self.webelement.find_element(*self._run_status_locator).click() | ||
self.webelement.find_element(*self._run_activate_locator).click() | ||
self.wait_for_ajax() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blank line contains whitespace