def wait_for_next(x: WebDriver): try: x.find_element(By.CSS_SELECTOR, '.js_has_member>div>a:nth-child(2)').click() return x.find_element(By.ID, "username") except: return False
def wait_for_next(driver: WebDriver): # 适用于按钮点击无反应的情况 try: driver.find_element(*locator).click() return driver.find_element(MobileBy.ID, "username") except StaleElementReferenceException: return False
def __check_element_remove(self, driver: WebDriver): try: driver.find_element(self.base_component_locator[0], self.base_component_locator[1]) return False except NoSuchElementException: return True
def wait_until_all_tabs_loaded(driver: WebDriver): """ When multiple windows are loading in the background, we wait until all are done """ original_window_handle = driver.current_window_handle for handle in driver.window_handles: driver.switch_to.window(handle) driver.find_element(By.CSS_SELECTOR, "html") driver.switch_to.window(original_window_handle)
def click_on_staleable_element(driver: WebDriver, el_locator, wait_seconds=1): """Clicks an element that can be modified between the time we find it and when we click on it""" time_start = time.time() while time.time() - time_start < wait_seconds: try: driver.find_element(*el_locator).click() break except exceptions.StaleElementReferenceException as e: logger.error(str(e)) time.sleep(0.1) else: raise exception.ElementNotFound(el_locator)
def wait_and_find(driver: WebDriver, locator_type: str, locator: str, timeout: int = 3, check_iframes: bool = True): """Search for element with `locator` and block if not found Parameters ---------- driver : selenium.webdriver.firefox.webdriver.WebDriver An instance of the Firefox webdriver locator_type : string A text representation of the attribute to search by, e.g. searching by `id`, `class name`, and so on. For a list of supported types, `import selenium.webdriver.common.by.By` and use `By.LINK_TEXT`, `By.ID`, and so on. locator : string The search string used to identify the candidate element. timeout : int, optional Time in seconds to block before throwing `NoSuchElementException`. The default is 3 seconds. check_iframes : bool, optional Set to `True` to also check all iframes contained directly in the current frame. Returns ------- selenium.webdriver.firefox.webelement.FirefoxWebElement Matching element (if any is found before `timeout`). Raises ------ NoSuchElementException Raised if no element is located with `locator` before `timeout`. """ if is_found(driver, locator_type, locator, timeout): return driver.find_element(locator_type, locator) else: if check_iframes: # this may return the browser with an iframe active driver.switch_to.default_content() iframes = driver.find_elements_by_tag_name('iframe') for iframe in iframes: driver.switch_to.default_content() driver.switch_to.frame(iframe) if is_found(driver, locator_type, locator, timeout=0): return driver.find_element(locator_type, locator) # If we get here, search also fails in iframes driver.switch_to.default_content() raise NoSuchElementException("Element not found during wait_and_find")
def check_if_element_is_not_present(driver: WebDriver, selector: Selector, *, element_name: str = ""): """Find element by CSS selector or it's ID.""" try: driver.find_element(by=selector.by, value=selector.value) found = True except NoSuchElementException: found = False with assertion_msg( f"Expected not to find '{element_name}' element identified by '{selector.value}' on {driver.current_url}" ): assert not found
async def authenticate( self, user: str, webdriver_session: WebDriver = None, request_state: str = str(uuid4()), ) -> str: """Authenticate and retrieve the code value""" # state = await self._get_state(request_state) params = urllib.parse.urlencode([(k, v) for k, v in { "response_type": "code", "client_id": self.client_id, "redirect_uri": self.redirect_uri, "state": request_state, }.items()]) authorize_url = f"{self.base_uri}/authorize?{params}" webdriver_session.get(authorize_url) webdriver_session.implicitly_wait(1) username = webdriver_session.find_element(By.ID, "username") username.send_keys(user + Keys.ENTER) webdriver_session.implicitly_wait(5) code = dict( urllib.parse.parse_qsl( urllib.parse.urlsplit( webdriver_session.current_url).query))["code"] return code
def find_element( driver: WebDriver, selector: Selector, *, element_name: str = "", wait_for_it: bool = True, take_screenshot: bool = True, ) -> WebElement: """Find element by CSS selector or it's ID.""" with selenium_action( driver, f"Could not find element called '{element_name}' using selector " f"'{selector.value}' on {driver.current_url}", screenshot=take_screenshot, ): element = driver.find_element(by=selector.by, value=selector.value) if wait_for_it and selector.is_visible: wait_for_visibility(driver, selector) if selector.disabled: check_if_element_is_disabled(element, element_name) elif selector.alternative_visibility_check: run_alternative_visibility_check( driver, element_name, selector, element=element, take_screenshot=take_screenshot, ) return element
def run(self, driver: WebDriver): for step in self.steps: if isinstance(step, dict): element=None if "id" in step.keys(): element=driver.find_element(*(By.ID, step['id'])) elif "xpath" in step.keys(): element=driver.find_element(*(By.XPATH, step['xpath'])) else: print(step.keys()) if 'input' in step.keys(): element.send_keys(step['input']) elif 'get' in step.keys(): element.get_attribute(step['get']) else: element.click()
def findElement(self, browser:WebDriver, e:str='', by:str='id'): by = by.upper() if self.isVisible(browser, by=by, e = e): # if True: self.scrollToTarget(browser,by=by, e=e) return browser.find_element(eval('By.'+by), e) else: raise ElementNotFoundException(e)
def _login( self, browser: WebDriver, user: str = "some-user", password: str = "some-password", go_to_login=True, ) -> WebDriver: if go_to_login: browser.get(urljoin(self.live_server_url, "workspace/login/")) username_input = browser.find_element(By.ID, "id_username") username_input.send_keys(user) password_input = browser.find_element(By.ID, "id_password") password_input.send_keys(password) browser.find_element( By.CSS_SELECTOR, ("#main-container > div.row > div > div > " "div.card-body > form > input.btn.btn-primary"), ).click() return browser
def scrollToTarget(self,browser:WebDriver,by='ID', e:str=''): if browser!=None and e != '': if ':' in e : e = e.split(':')[0] e = browser.find_element(eval('By.'+by),e) # browser.execute_script("arguments[0].scrollIntoViewIfNeeded(true);", target) browser.execute_script("arguments[0].scrollIntoView();", e) else: raise ElementNotFoundException(e)
def play_video(driver: WebDriver, *, play_time: int = 5): video_load_delay = 2 video = driver.find_element(by=PROMO_VIDEO.by, value=PROMO_VIDEO.value) scroll_to(driver, video) video.click() play_js = f'document.querySelector("{PROMO_VIDEO.value}").play()' pause = f'document.querySelector("{PROMO_VIDEO.value}").pause()' driver.execute_script(play_js) if play_time: time.sleep(play_time + video_load_delay) driver.execute_script(pause)
def init_lihkg_context(browser: WebDriver) -> WebElement: ''' We need to open a LIHKG page and then jump to the API URL. This process is wrapped as the LIHKG context. ''' browser.get('https://lihkg.com/thread/2256553/page/1') body = WebDriverWait(browser, timeout=5).until( EC.presence_of_element_located((By.TAG_NAME, 'body')) ) element_id = random_string() browser.execute_script(f'a = document.createElement("a"); a.id = arguments[1]; a.target = "_blank"; arguments[0].appendChild(a)', body, element_id) context = browser.find_element(By.ID, element_id) return context
def check_for_sections( driver: WebDriver, all_sections: dict, sought_sections: List[str], *, desktop: bool = True, mobile: bool = False, horizontal: bool = False, ): print(sought_sections) print(all_sections) for name in sought_sections: if desktop: selectors = get_desktop_selectors(all_sections[name.lower()]) elif mobile: selectors = get_mobile_selectors(all_sections[name.lower()]) elif horizontal: selectors = get_horizontal_selectors(all_sections[name.lower()]) else: raise KeyError( "Please choose from desktop, mobile or horizontal (mobile) selectors" ) for key, selector in selectors.items(): with selenium_action( driver, f"Could not find element: '{key} → {selector.by} → {selector.value}'" f" on {driver.current_url}", ): element = driver.find_element(by=selector.by, value=selector.value) if selector.is_visible: with scroll_to_element_if_not_visible(driver, element, section=name, name=key): wait_for_element_visibility(driver, element) logging.debug( f"'{key} → {selector.by} → {selector.value}' is visible") else: if selector.alternative_visibility_check: run_alternative_visibility_check(driver, key, selector, element=element) else: logging.debug( f"Skipping visibility check for '{key} → {selector.by} → " f"{selector.value}' as its selector is flagged as not visible" )
def find_element(driver: WebDriver, selector: Selector, *, wait_for_it: bool = True) -> WebElement: """Find element by CSS selector or it's ID.""" with selenium_action( driver, "Couldn't find element called '%s' using selector '%s' on" " %s", selector.name, selector.value, driver.current_url, ): element = driver.find_element(by=selector.by, value=selector.value) if wait_for_it: wait_for_visibility(driver, selector) return element
def proceed_to_login_console(driver: WebDriver): """ Proceed to the login console, if needed to confirm this action in a page that appears before. This is required to be as a solo function, because the driver initializes in the login_ui function. Function needs to be called just before login Args: driver (Selenium WebDriver) Returns: None """ login_loc = locators[get_ocp_version()]["login"] if driver.title == login_loc["pre_login_page_title"]: proceed_btn = driver.find_element( by=login_loc["proceed_to_login_btn"][1], value=login_loc["proceed_to_login_btn"][0], ) proceed_btn.click() WebDriverWait(driver, 60).until(ec.title_is(login_loc["login_page_title"]))
def sign_in(selenium: WebDriver, auth: Auth): # find and select Kinto Account Auth for login kinto_auth_radio_button: WebElement = selenium.find_element( By.XPATH, "//input[@value='accounts']") assert kinto_auth_radio_button, "Kinto Account Auth radio button not found" kinto_auth_radio_button.click() # ensure account credentials fields render account_creds_title: WebElement = selenium.find_element( By.ID, "root_credentials__title") assert account_creds_title, "Account credentials title not found" assert account_creds_title.text == "Account credentials*" assert account_creds_title.is_displayed() # enter login username account_creds_user: WebElement = selenium.find_element( By.ID, "root_credentials_username") assert account_creds_user, "Account credentials username entry not found" assert account_creds_user.is_displayed() account_creds_user.send_keys(auth[0]) # enter login password account_creds_pass: WebElement = selenium.find_element( By.ID, "root_credentials_password") assert account_creds_pass, "Account credentials password entry not found" assert account_creds_pass.is_displayed() account_creds_pass.send_keys(auth[1]) # sign in sign_in_button: WebElement = selenium.find_element(By.CLASS_NAME, "btn-info") assert sign_in_button, "Sign in button not found" assert sign_in_button.text == "Sign in using Kinto Account Auth" assert sign_in_button.is_displayed() sign_in_button.click() # determine if successfully logged in to admin home page try: server_info: WebElement = selenium.find_element( By.XPATH, "//div[@class='card-header' and contains(., 'Server information')]", ) assert server_info, "Server information not found" assert server_info.text == "Server information" assert server_info.is_displayed() except NoSuchElementException: pytest.fail("Login was unsuccessful")
def wait_for_next(x: WebDriver): try: x.find_element(By.CSS_SELECTOR, ".js_add_member:nth-child(2)").click() return x.find_element(By.ID, "username") except: return False
def run(driver: WebDriver): nonlocal no if not no: elem = driver.find_element(By.XPATH, "//a[text()='投票']") if not elem: elem = driver.find_element(By.XPATH, "//a[text()='今日已投票']") if elem: driver.delete_all_cookies() driver.refresh() return None elem.click() elem_container = driver.find_element_by_class_name( "modal__container") if elem_container.is_displayed(): no += 1 return elem_container elif no == 1: elem_vote_options = driver.find_elements( By.XPATH, "//div/div/label[@class='label']") if not elem_vote_options: return None for elem in elem_vote_options: if not elem.is_displayed(): break elem.click() for_input = driver.find_element_by_id( elem.get_attribute("for")) if not for_input.is_selected(): break else: no += 1 return elem_vote_options if no == 2: driver.add_cookie({ "name": "uuid", "value": generate_uuid(), "domain": ".businessweekly.com.tw", "size": 40, }) elem = None try: elem = driver.find_element(By.XPATH, r"//a[text()='確認送出']") if elem and elem.is_enabled(): elem.click() except Exception as e: if driver.find_element_by_id("gdrp-el"): driver.execute_script( """document.getElementById("gdrp-el").remove();""") finally: elem_container = driver.find_element_by_class_name( "modal__container") if elem_container and elem_container.find_element( By.XPATH, "//img[@alt='投票完成']"): no += 1 return True if "投票完成" in driver.page_source: no += 1 return True return None
def _find_element(browser: WebDriver, by, arg): _wait(browser).until(lambda x: browser.find_element(by, arg)) element = browser.find_element(by, arg) _wait(browser).until(EC.visibility_of(element)) return element
def call_rate( update_loc: Union[str, PathLike, Engine, Connection, None] = None, revise_rows: Union[str, int] = "nodup", save_loc: Union[str, PathLike, Engine, Connection, None] = None, only_get: bool = False, driver: WebDriver = None) -> pd.DataFrame: """Get 1-day call interest rate data. This function requires a Selenium webdriver. It can be provided in the driver parameter, or it will attempt to configure a Chrome webdriver. Parameters ---------- update_loc : str, os.PathLike, SQLAlchemy Connection or Engine, or None, \ default None Either Path or path-like string pointing to a directory where to find a CSV for updating, SQLAlchemy connection or engine object, or ``None``, don't update. revise_rows : {'nodup', 'auto', int} Defines how to process data updates. An integer indicates how many rows to remove from the tail of the dataframe and replace with new data. String can either be ``auto``, which automatically determines number of rows to replace from the inferred data frequency, or ``nodup``, which replaces existing periods with new data. save_loc : str, os.PathLike, SQLAlchemy Connection or Engine, or None, \ default None Either Path or path-like string pointing to a directory where to save the CSV, SQL Alchemy connection or engine object, or ``None``, don't save. only_get : bool, default False If True, don't download data, retrieve what is available from ``update_loc``. driver : selenium.webdriver.chrome.webdriver.WebDriver, default None Selenium webdriver for scraping. If None, build a Chrome webdriver. Returns ------- Daily call rate : pd.DataFrame """ name = "call" if only_get is True and update_loc is not None: output = ops._io(operation="update", data_loc=update_loc, name=name) if not output.equals(pd.DataFrame()): return output if driver is None: driver = _build() driver.get(urls[name]["dl"]["main"]) start = driver.find_element( by="name", value="ctl00$ContentPlaceHolder1$dateDesde$dateInput") start.clear() start.send_keys("01/01/2002") end = driver.find_element( by="name", value="ctl00$ContentPlaceHolder1$dateHasta$dateInput") end.clear() end.send_keys(dt.datetime.now().strftime("%d/%m/%Y")) submit = driver.find_element(by="id", value="ContentPlaceHolder1_LinkFiltrar") submit.click() time.sleep(5) tables = pd.read_html(driver.page_source, decimal=",", thousands=".") driver.quit() raw = tables[8].iloc[:, :-2] call = raw.set_index("FECHA") call.index = pd.to_datetime(call.index, format="%d/%m/%Y") call.sort_index(inplace=True) call.columns = ["Tasa call a 1 día: Promedio", "Tasa call a 1 día: Máximo", "Tasa call a 1 día: Mínimo"] if update_loc is not None: previous_data = ops._io(operation="update", data_loc=update_loc, name=name) call = ops._revise(new_data=call, prev_data=previous_data, revise_rows=revise_rows) call = call.apply(pd.to_numeric, errors="coerce") metadata._set(call, area="Sector financiero", currency="UYU", inf_adj="No", unit="Tasa", seas_adj="NSA", ts_type="-", cumperiods=1) if save_loc is not None: ops._io(operation="save", data_loc=save_loc, data=call, name=name) return call
class BaseCase(unittest.TestCase): ''' A base test case that wraps a bunch of methods from tools for easier access. You can also add your own methods here. ''' def __init__(self, *args, **kwargs): super(BaseCase, self).__init__(*args, **kwargs) try: self.driver = WebDriver() except Exception: pass self.environment = None def find_visible_elements(self, selector, by=By.CSS_SELECTOR): return page_interactions.find_visible_elements(self.driver, selector, by) def hover_on_element(self, selector): return page_interactions.hover_on_element(self.driver, selector) def hover_and_click(self, hover_selector, click_selector, click_by=By.CSS_SELECTOR, timeout=5): return page_interactions.hover_and_click(self.driver, hover_selector, click_selector, click_by, timeout) def is_element_present(self, selector, by=By.CSS_SELECTOR): return page_interactions.is_element_present(self.driver, selector, by) def is_element_visible(self, selector, by=By.CSS_SELECTOR): return page_interactions.is_element_visible(self.driver, selector, by) def is_text_visible(self, text, selector, by=By.CSS_SELECTOR): return page_interactions.is_text_visible(self.driver, text, selector, by) def jquery_click(self, selector): return self.driver.execute_script("jQuery('%s').click()" % selector) def click(self, selector): ele = self.driver.find_element(by=By.CSS_SELECTOR, value=selector) return ele.click() def scroll_to(self, selector): self.driver.execute_script("jQuery('%s')[0].scrollIntoView()" % selector) def scroll_click(self, selector): self.scroll_to(selector) time.sleep(0.1) self.click(selector) def jq_format(self, code): """ Use before throwing raw code such as 'div[tab="advanced"]' into jQuery. Similar to "json.dumps(value)". The first replace should take care of everything. Now see what else there is. """ code = code.replace('\\','\\\\').replace('\t',' ').replace('\n', '\\n').replace('\"','\\\"').replace('\'','\\\'').replace('\r', '\\r').replace('\v', '\\v').replace('\a', '\\a').replace('\f', '\\f').replace('\b', '\\b').replace('\u', '\\u') return code def set_value(self, selector, value): val = json.dumps(value) return self.driver.execute_script("jQuery('%s').val(%s)" % (selector, val)) def update_text_value(self, selector, new_value, timeout=5, retry=False): """ This method updates a selector's text value with a new value @Params selector - the selector with the value to change new_value - the new value for the text field where the selector points to timeout - how long to want for the selector to be visible before timing out retry - if text update fails, try the jQuery version (Warning: don't use this if update_text_value() takes you to a new page, or if it resets the value (such as using [backslash n] for the enter key) """ element = self.wait_for_element_visible(selector, timeout=timeout) element.clear() element.send_keys(new_value) if retry: if element.get_attribute('value') != new_value: logging.debug('update_text_value is falling back to jQuery!') # Since selectors with quotes inside of quotes such as 'div[data-tab-name="advanced"]' break jQuery, format them first selector = self.jq_format(selector) self.set_value(selector, new_value) time.sleep(0.5) def wait_for_element_present(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_present(self.driver, selector, by, timeout) def wait_for_element_visible(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_visible(self.driver, selector, by, timeout) def wait_for_text_visible(self, text, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_text_visible(self.driver, text, selector, by, timeout) def wait_for_element_absent(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_absent(self.driver, selector, by, timeout) def wait_for_element_not_visible(self, selector, by=By.CSS_SELECTOR, timeout=30): return page_loads.wait_for_element_not_visible(self.driver, selector, by, timeout) def wait_for_and_switch_to_alert(self, timeout=30): return page_loads.wait_for_and_switch_to_alert(self.driver, timeout)
def transaction_parser( cls, driver: WebDriver, account: AbstractAccount ) -> Iterator[Optional['SberbankTransaction']]: """Parse Sberbank transaction.""" transactions_table = driver.find_element(By.ID, 'simpleTable0') with suppress(NoSuchElementException): driver.find_element(By.XPATH, "//div[contains(@class, 'emptyText')]") logger.info( f'Not found new transactions for account {account.name}') return if driver.find_element(By.ID, 'pagination').is_displayed(): # Many transactions. Increase the number of elements per page driver.find_elements( By.XPATH, "//span[contains(@class, 'paginationSize')]")[-1].click() transactions_table = driver.find_element(By.ID, 'simpleTable0') while True: curr_day_transactions = [] prev_transaction_data = cls._transaction_time_parse('Сегодня') for transaction_el in transactions_table.find_elements( By.XPATH, ".//tr[contains(@class, 'ListLine')]"): raw_info = [ i.text for i in transaction_el.find_elements(By.XPATH, "./td") ] curr_transaction_date = cls._transaction_time_parse( raw_info[3]) raw_cost, raw_currency = raw_info[4].rsplit(' ', 1) raw_transaction = { 'account_name': account.name, 'tr_time': curr_transaction_date, 'cost': replace_formatter(raw_cost, delete_symbols=' ', custom={',': '.'}), 'currency': currency_converter(raw_currency), 'description': raw_info[0].rsplit('\n', 1)[0], } if prev_transaction_data == curr_transaction_date: logger.debug( f'add to {curr_transaction_date} transaction {raw_transaction}' ) curr_day_transactions.append(raw_transaction) else: logger.debug( f'return transactions {curr_day_transactions} for {prev_transaction_data}' ) yield from cls._add_custom_unique_tr_id( curr_day_transactions) curr_day_transactions.clear() prev_transaction_data = curr_transaction_date logger.debug( f'add to {curr_transaction_date} transaction {raw_transaction}' ) curr_day_transactions.append(raw_transaction) paginator = transactions_table.find_element(By.ID, 'pagination') if paginator.is_displayed(): # go to next page paginator_next = paginator.find_elements( By.XPATH, ".//table[contains(@class, 'tblPagin')]//td")[2] with suppress(NoSuchElementException): # if only one page with transaction results - be error here. Ignoring... button = paginator_next.find_element( By.XPATH, ".//div[contains(@class, 'activePaginRightArrow')]") if button.get_attribute('class').startswith('inactive'): # if last page logger.debug( f'return transactions {curr_day_transactions} for {prev_transaction_data}' ) yield from cls._add_custom_unique_tr_id( curr_day_transactions) break button.click() def wait_new_table(): # waiting new page with transactions WebDriverWait(driver, TIMEOUT).until( expected_conditions.presence_of_element_located( (By.ID, 'simpleTable0'))) retry = Retry( function=wait_new_table, error=SeleniumTimeoutException, err_msg= (f'Error. WebDriver not found page with new transactions for timeout {TIMEOUT}.' ' Please, check your network connection'), max_attempts=3) retry() else: logger.debug( f'return transactions {curr_day_transactions} for {prev_transaction_data}' ) yield from cls._add_custom_unique_tr_id(curr_day_transactions) break
def wait_for_next(x: WebDriver): try: x.find_element(*locator).send_keys(value) return True except: return False
def __call__(self, driver: WebDriver): element = driver.find_element(By.XPATH, f'//button[.="{self.text}"]') return element or False
def _click_when_available(browser: WebDriver, by, arg): _wait(browser).until(lambda x: browser.find_element(by, arg)) element = browser.find_element(by, arg) _wait(browser).until(EC.visibility_of(element)) _click_element(browser, element) return element
def wait_for_next(x: WebDriver): try: x.find_element(*locator).click() return x.find_element(By.ID, "username") except: return False
async def test_review_signoff( base_url: str, selenium: WebDriver, make_client: ClientFactory, setup_auth: Auth, editor_auth: Auth, reviewer_auth: Auth, source_bucket: str, source_collection: str, skip_server_setup: bool, keep_existing: bool, ): editor_client = make_client(editor_auth) reviewer_client = make_client(reviewer_auth) editor_id = (await editor_client.server_info())["user"]["id"] reviewer_id = (await reviewer_client.server_info())["user"]["id"] # Setup remote server. if not skip_server_setup: setup_client = make_client(setup_auth) await setup_client.create_bucket(if_not_exists=True) await setup_client.create_collection( permissions={"write": [editor_id, reviewer_id]}, if_not_exists=True, ) data = JSONPatch([{ "op": "add", "path": "/data/members/0", "value": editor_id }]) await setup_client.patch_group(id=f"{source_collection}-editors", changes=data) data = JSONPatch([{ "op": "add", "path": "/data/members/0", "value": reviewer_id }]) await setup_client.patch_group(id=f"{source_collection}-reviewers", changes=data) if not keep_existing: await setup_client.delete_records() dest_bucket = (await signed_resource(editor_client))["destination"]["bucket"] # Sample data. await editor_client.create_record(data={"testing": 123}) await editor_client.patch_collection(data={"status": "to-review"}) # Start browsing. selenium.get(base_url) sign_in(selenium, reviewer_auth) selenium.get( base_url + f"#/buckets/{source_bucket}/collections/{source_collection}/simple-review" ) selenium.refresh() try: approve_button: WebElement = selenium.find_element( By.XPATH, "//button[contains(., 'Approve')]") except NoSuchElementException: print(selenium.page_source) # CI debugging. raise assert approve_button, "Approve button not found" assert approve_button.text == "Approve" assert approve_button.is_displayed() reject_button: WebElement = selenium.find_element( By.XPATH, "//button[contains(., 'Reject')]") assert reject_button, "Reject button not found" assert reject_button.text == "Reject" assert reject_button.is_displayed() approve_button.click() # find and click show readonly buckets/collections readonly_checkbox: WebElement = selenium.find_element( By.ID, "read-only-toggle") assert readonly_checkbox, "Readonly checkbox not found" assert readonly_checkbox.is_displayed() readonly_checkbox.click() # find and click on main bucket product-integrity collection product_integrity: WebElement = selenium.find_element( By.XPATH, f"//a[@href='#/buckets/{dest_bucket}/collections/{source_collection}/records' and contains(., '{source_collection}')]", ) assert ( product_integrity ), f"{source_collection} collection not found under {dest_bucket} bucket" assert product_integrity.is_displayed() product_integrity.click() # find and ensure record was properly signed to destination bucket data: WebElement = selenium.find_element(By.XPATH, "//code") assert ( data ), f"Record not found in {source_collection} collection under {dest_bucket} bucket" assert data.is_displayed() assert data.text == '{"testing":123}'
def bonds(update_loc: Union[str, PathLike, Engine, Connection, None] = None, revise_rows: Union[str, int] = "nodup", save_loc: Union[str, PathLike, Engine, Connection, None] = None, only_get: bool = False, driver: WebDriver = None) -> pd.DataFrame: """Get interest rate yield for Uruguayan US-denominated bonds, inflation-linked bonds and peso bonds. This function requires a Selenium webdriver. It can be provided in the driver parameter, or it will attempt to configure a Chrome webdriver. Parameters ---------- update_loc : str, os.PathLike, SQLAlchemy Connection or Engine, or None, \ default None Either Path or path-like string pointing to a directory where to find a CSV for updating, SQLAlchemy connection or engine object, or ``None``, don't update. revise_rows : {'nodup', 'auto', int} Defines how to process data updates. An integer indicates how many rows to remove from the tail of the dataframe and replace with new data. String can either be ``auto``, which automatically determines number of rows to replace from the inferred data frequency, or ``nodup``, which replaces existing periods with new data. save_loc : str, os.PathLike, SQLAlchemy Connection or Engine, or None, \ default None Either Path or path-like string pointing to a directory where to save the CSV, SQL Alchemy connection or engine object, or ``None``, don't save. only_get : bool, default False If True, don't download data, retrieve what is available from ``update_loc``. driver : selenium.webdriver.chrome.webdriver.WebDriver, default None Selenium webdriver for scraping. If None, build a Chrome webdriver. Returns ------- Daily bond yields in basis points : pd.DataFrame """ name = "bonds" if only_get is True and update_loc is not None: output = ops._io(operation="update", data_loc=update_loc, name=name) if not output.equals(pd.DataFrame()): return output if driver is None: driver = _build() dfs = [] for url in urls[name]["dl"].values(): driver.get(url) start = driver.find_element( by="name", value="ctl00$ContentPlaceHolder1$dateDesde$dateInput") start.clear() start.send_keys("01/01/2000") end = driver.find_element( by="name", value="ctl00$ContentPlaceHolder1$dateHasta$dateInput") end.clear() end.send_keys(dt.datetime.now().strftime("%d/%m/%Y")) submit = driver.find_element(by="id", value="ContentPlaceHolder1_LinkFiltrar") submit.click() time.sleep(10) tables = pd.read_html(driver.page_source, decimal=",", thousands=".") raw = tables[8] df = raw.set_index("FECHA") df.index = pd.to_datetime(df.index, format="%d/%m/%Y") df.sort_index(inplace=True) df = df.loc[:, df.columns.isin(["BPS", "RENDIMIENTO"])] df.columns = [url] dfs.append(df) driver.quit() output = dfs[0].join(dfs[1], how="outer").join(dfs[2], how="outer") output.columns = ["Bonos soberanos en dólares", "Bonos soberanos en UI", "Bonos soberanos en pesos"] if update_loc is not None: previous_data = ops._io(operation="update", data_loc=update_loc, name=name) output = ops._revise(new_data=output, prev_data=previous_data, revise_rows=revise_rows) output = output.apply(pd.to_numeric, errors="coerce") metadata._set(output, area="Sector financiero", currency="-", inf_adj="No", unit="PBS", seas_adj="NSA", ts_type="-", cumperiods=1) metadata._modify_multiindex(output, levels=[3, 4], new_arrays=[["USD", "UYU", "UYU"], ["No", "Const.", "No"]]) if save_loc is not None: ops._io(operation="save", data_loc=save_loc, data=output, name=name) return output