class AdminHeader1(BasePageWidget): def __init__(self, owner, locatordict={}): super(AdminHeader1,self).__init__(owner,locatordict) # load hub's classes AdminHeader_Locators = self.load_class('AdminHeader_Locators') # update this object's locator defaults self.locators.update(AdminHeader_Locators.locators) # update the locators with those from the owner self.update_locators_from_owner() # setup page object's components self.logout = Link(self,{'base':'logout'}) # update the component's locators with this objects overrides self._updateLocators() def goto_logout(self): self.logout.click() self.logout.wait_until_invisible()
class Login2(FormBase): """ login page found on nanohub.org where the user must choose their login method before filling out the login form. This object works for local HUB login. """ def __init__(self, owner, locatordict={}): super(Login2,self).__init__(owner,locatordict) # load hub's classes Login_Locators = self.load_class('Login_Locators') # update this object's locator self.locators.update(Login_Locators.locators) # update the locators with those from the owner self.update_locators_from_owner() # setup page object's components self.change_account = Link(self,{'base':'change_account'}) self.hub_signin = Link(self,{'base':'hub_signin'}) self.username = Text(self,{'base':'username'}) self.password = Text(self,{'base':'password'}) self.remember = Checkbox(self,{'base':'remember'}) self.remind = Link(self,{'base':'remind'}) self.reset = Link(self,{'base':'reset'}) self.register = Link(self,{'base':'register'}) self.fields += ['username','password','remember'] # update the component's locators with this objects overrides self._updateLocators() def login_as(self,username,password,remember=False): """login to the website using the provided credentials""" self.logger.debug("browser logging in as user \"%s\"" % (username)) data = { 'username' : username, 'password' : password, } # handle login forms that don't have remember links # like purduehubu if self.remember.is_present(): data['remember'] = remember # reset the login user if necessary # if a user has previously logged in, # their username/email is hard coded in the form. # this clicks the "sign in with a different account" link if self.change_account.is_displayed(): self.change_account.click() message = 'while changing hub account' self.change_account.wait_until_invisible(message) # enable the hidden hub login form if self.hub_signin.is_displayed(): self.hub_signin.click() message = 'while choosing local hub login' self.hub_signin.wait_until_invisible(message) # populate the hub login form self.submit_form(data) # we use the presence of the username and password fields # as a hint that are still logging in. check the password # field first because whatever page we land on after login # probably won't have a password field, but if it does # we then check for the username field. different hubs # land on different pages, and these pages may use the same # locator as the username or password field. hopefully the # probability of the landing page having both is low. # another solution is to just let the login_as function perform # the login, and let another function go to the myaccount # or dashboard page and check for the logout link. # we user the username and password fields because some hubs # seem to hide the logout link (manufacturinghub) try: message = 'while verifying login: password field still present' self.password.wait_until_not_present(message) except TimeoutException: message = 'while verifying login: username and' \ + ' password fields still present' self.username.wait_until_not_present(message)
class Header(BasePageWidget): def __init__(self, owner, locatordict={}): super(Header,self).__init__(owner,locatordict) # load hub's classes Header_Locators = self.load_class('Header_Locators') # update this object's locator self.locators.update(Header_Locators.locators) # update the locators with those from the owner self.update_locators_from_owner() # setup page object's components self.login = Link(self,{'base':'login'}) self.register = Link(self,{'base':'register'}) self.logout = Link(self,{'base':'logout'}) self.myaccount = Link(self,{'base':'myaccount'}) # self.search = Search(self,{'base':'search'}) # update the component's locators with this objects overrides self._updateLocators() def _checkLocatorsLoggedOut(self): widgets = [self.login,self.register] self._checkLocators(widgets=widgets,cltype='LoggedOut') def _checkLocatorsLoggedIn(self): widgets = [self.logout,self.myaccount] self._checkLocators(widgets=widgets,cltype='LoggedIn') def goto_login(self): """click the login link""" return self.login.click() def goto_register(self): """click the register link""" return self.register.click() def goto_logout(self): """click the logout link""" self.logout.click() message = 'logout button visible while trying to logout' self.logout.wait_until_invisible(message) return def goto_myaccount(self): """click the link to go to the member's myaccount page""" return self.myaccount.click() def is_logged_in(self): """check if user is logged in, returns True or False""" return self.logout.is_displayed() def get_account_number(self): """return the user's account number based on the "My Account" url""" url = self.myaccount.get_attribute('href') if not url: raise RuntimeError("link '%s' has no href" % (self.myaccount.locator)) path = urlparse.urlsplit(url)[2] if not path: raise RuntimeError("url '%s' has no path" % (url)) matches = re.search("/members/(\d+)",path) if matches is None: raise RuntimeError("path '%s' does not contain an account number" % (path)) account_number = matches.group(1) return account_number
class ResourcesToolFileUploadRow(ItemListItem): def __init__(self, owner, locatordict={}, row_number=0): super(ResourcesToolFileUploadRow,self).__init__(owner,locatordict,row_number) # load hub's classes ResourcesToolFileUploadRow_Locators = self.load_class('ResourcesToolFileUploadRow_Locators') # update this object's locator self.locators.update(ResourcesToolFileUploadRow_Locators.locators) # update the locators with those from the owner self.update_locators_from_owner() # setup page object's components self.name = TextReadOnly(self,{'base':'name'}) self.show = Link(self,{'base':'show'},self._onClickShow) self.delete = Link(self,{'base':'delete'},self._onClickDelete) # update the component's locators with this objects overrides self._updateLocators() def _onClickShow(self): self.show.wait_until_invisible() def _onClickDelete(self): self.delete.wait_until_invisible() def rename(self,name): """rename the uploaded document""" # use action chains to double click on the name, # and fill in a new value # the documentation above the widget says the user # needs to double click, but it appears a single # click will work. it also says tab or enter # save, but i don't think these keys do anything e = self.name.wait_until_visible() ActionChains(self._browser)\ .double_click(e)\ .perform() t = Text(self,{'base':'rename_text'}) s = Button(self,{'base':'rename_save'}) t.wait_until_visible() t.value = name s.click() s.wait_until_not_present() del t del s def value(self): """return a dictionary with the name and size properties""" # show text looks like this: # <filename>, <size> <units> # simulink.jpg, 41.99 Kb size = self.show.text().split(',')[1].strip() return({'name':self.name.text(), 'size':size})
class MembersDashboardMySessionsItem(ItemListItem): def __init__(self, owner, locatordict={},row_number=0): super(MembersDashboardMySessionsItem,self)\ .__init__(owner,locatordict,row_number) # load hub's classes MembersDashboardMySessionsItem_Locators = \ self.load_class('MembersDashboardMySessionsItem_Locators') # update this object's locator self.locators.update(MembersDashboardMySessionsItem_Locators.locators) # update the locators with those from the owner self.update_locators_from_owner() # setup page object's components self.quick_launch = Link(self,{'base':'quick_launch'}) self.title = Link(self,{'base':'title'}) self.snapshotlink = Link(self,{'base':'snapshotlink'}) self.access_time = TextReadOnly(self,{'base':'access_time'}) self.session_owner = Link(self,{'base':'session_owner'}) self.resume = Link(self,{'base':'resume'}) self.terminate = Link(self,{'base':'terminate'}) self.disconnect = Link(self,{'base':'disconnect'}) # update the component's locators with this objects overrides self._updateLocators() def value(self): """return a dictionary of properties for this session""" # open the slide down window if necessary was_open = True if not self.is_slide_open(): was_open = False self.toggle_slide() properties = { 'title' : self.title.text(), 'access_time' : self.get_last_accessed()[1], 'session_owner' : self.get_session_owner(), 'session_number' : self.get_session_number(), } if was_open is False: # close the slide down window # if it was originally closed self.toggle_slide() return properties def quick_launch_session(self): """use the quick_launch link to open the session""" self.quick_launch.click() return def get_title(self): """return the title of the session""" return self.title.text() def toggle_slide(self): """open or close the session item slide down""" check_invisible = self.resume.is_displayed() self.title.click() if check_invisible: message = 'while closing toggle, waiting for resume to disappear' self.resume.wait_until_invisible(message) else: message = 'while closing toggle, waiting for resume to appear' self.resume.wait_until_visible(message) return def is_slide_open(self): """check if the session item slide down is open""" return (self.title.is_displayed() and self.resume.is_displayed()) def get_last_accessed(self): """return the last accessed time stamp as a string and datetime object""" at_text = self.access_time.value dt_text = re.sub(r'Last Accessed:\s+','',at_text,flags=re.IGNORECASE) # dt_text should look something like this: # October 12, 2013 @ 12:44am dt = datetime.datetime.strptime(dt_text,'%B %d, %Y @ %I:%M%p') return (dt_text,dt) def get_session_owner(self): """return the session owner""" owner_text = None if self.session_owner.is_displayed(): owner_text = self.session_owner.text() return owner_text def get_session_number(self): """return the session number based on the url for the "open" link""" self.logger.debug('retrieving session number') snre = re.compile(r'=([0-9]+)') href = self.resume.get_attribute('href') self.logger.debug('href = %s' % (href)) match = snre.search(href) if match: session_number = int(match.group(1)) else: session_number = None self.logger.debug('session_number = %d' % (session_number)) return session_number def resume_session(self): """open this session""" return self.resume.click() def terminate_session(self,confirm=True): """terminate this session""" self.terminate.click() alert = self._browser.switch_to_alert() if confirm: self.logger.debug('accepting alert') alert.accept() else: self.logger.debug('dismissing alert') alert.dismiss() self._browser.switch_to_default_content() def disconnect_session(self,confirm=True): """disconnect from this shared session""" self.disconnect.click() alert = self._browser.switch_to_alert() if confirm: self.logger.debug('accepting alert') alert.accept() else: self.logger.debug('dismissing alert') alert.dismiss() self._browser.switch_to_default_content()