tir-framework 2.14.2__tar.gz → 2.14.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tir_framework-2.14.2/tir_framework.egg-info → tir_framework-2.14.3}/PKG-INFO +1 -1
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/base.py +9 -2
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/webapp_internal.py +168 -41
- tir_framework-2.14.3/tir/version.py +1 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3/tir_framework.egg-info}/PKG-INFO +1 -1
- tir_framework-2.14.2/tir/version.py +0 -1
- {tir_framework-2.14.2 → tir_framework-2.14.3}/LICENSE +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/MANIFEST.in +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/README.md +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/setup.cfg +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/setup.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tests/test_log.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tests/test_utils.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tests/test_webapp_internal_clicktree.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/__init__.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/main.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/apw_internal.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/base_database.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/config.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/data/sx3.csv +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/linux64/geckodriver +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/windows/chromedriver.exe +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/windows/electron/chromedriver.exe +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/windows/geckodriver.exe +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/enumerations.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/events.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/language.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/log.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/logging_config.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/numexec.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/psutil_info.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/router.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/third_party/screen_size.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/third_party/xpath_soup.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/utils.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/poui_internal.py +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir_framework.egg-info/SOURCES.txt +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir_framework.egg-info/dependency_links.txt +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir_framework.egg-info/requires.txt +0 -0
- {tir_framework-2.14.2 → tir_framework-2.14.3}/tir_framework.egg-info/top_level.txt +0 -0
|
@@ -586,7 +586,14 @@ class Base(unittest.TestCase):
|
|
|
586
586
|
tries += 1
|
|
587
587
|
|
|
588
588
|
if filtered_iframe:
|
|
589
|
-
|
|
589
|
+
if self.webapp_shadowroot():
|
|
590
|
+
shadow_iframe = self.find_shadow_element('iframe', filtered_iframe)
|
|
591
|
+
if shadow_iframe:
|
|
592
|
+
self.driver.switch_to.frame(shadow_iframe[0])
|
|
593
|
+
else:
|
|
594
|
+
self.driver.switch_to.frame(filtered_iframe)
|
|
595
|
+
else:
|
|
596
|
+
self.driver.switch_to.frame(filtered_iframe)
|
|
590
597
|
|
|
591
598
|
|
|
592
599
|
def filter_active_iframe(self, iframes):
|
|
@@ -1632,7 +1639,7 @@ class Base(unittest.TestCase):
|
|
|
1632
1639
|
|
|
1633
1640
|
# Filter blocked elements only when WaitProcessing is not in the stack
|
|
1634
1641
|
# and blocked-container filtering is enabled.
|
|
1635
|
-
if not self.search_stack('WaitProcessing') and self.filter_blocked_containers:
|
|
1642
|
+
if not self.search_stack('WaitProcessing') and not self.search_stack('IfExists') and self.filter_blocked_containers:
|
|
1636
1643
|
non_blocked_elements = list(filter(lambda x: hasattr(x, 'attr') and 'blocked' not in x.attrs, elements))
|
|
1637
1644
|
|
|
1638
1645
|
if isinstance(non_blocked_elements, list):
|
|
@@ -1997,6 +1997,7 @@ class WebappInternal(Base):
|
|
|
1997
1997
|
logger().debug(f'wa-dialog layers: {container_layers}')
|
|
1998
1998
|
|
|
1999
1999
|
if not success:
|
|
2000
|
+
self.restart_counter += 1
|
|
2000
2001
|
self.log_error('Home screen not found!')
|
|
2001
2002
|
|
|
2002
2003
|
# wait trasitions between screens to avoid errors in layers number
|
|
@@ -4862,6 +4863,68 @@ class WebappInternal(Base):
|
|
|
4862
4863
|
logger().warning(f"Warning SetLateralMenu click last item method exception: {str(e)} ")
|
|
4863
4864
|
|
|
4864
4865
|
|
|
4866
|
+
def get_shadowroot_button(self, button, term_button, position, check_error=True):
|
|
4867
|
+
"""
|
|
4868
|
+
[Internal]
|
|
4869
|
+
|
|
4870
|
+
Captures the button element inside a shadowroot container.
|
|
4871
|
+
|
|
4872
|
+
:param button: Button caption to be located.
|
|
4873
|
+
:type button: str
|
|
4874
|
+
:param term_button: CSS selector used to locate the button candidates.
|
|
4875
|
+
:type term_button: str
|
|
4876
|
+
:param position: Index of the button among the filtered candidates.
|
|
4877
|
+
:type position: int
|
|
4878
|
+
:param check_error: Whether errors should be checked while waiting. - **Default:** True
|
|
4879
|
+
:type check_error: bool
|
|
4880
|
+
|
|
4881
|
+
:return: The located button element (Tag or Selenium element) or None if not found.
|
|
4882
|
+
|
|
4883
|
+
Usage:
|
|
4884
|
+
|
|
4885
|
+
>>> next_button = self.get_shadowroot_button(button, term_button, position, check_error)
|
|
4886
|
+
"""
|
|
4887
|
+
regex = r"(<[^>]*>)?"
|
|
4888
|
+
next_button = None
|
|
4889
|
+
filtered_buttons = []
|
|
4890
|
+
|
|
4891
|
+
self.wait_element_timeout(term=button, scrap_type=enum.ScrapType.MIXED, optional_term=term_button, timeout=10, step=0.1, check_error=check_error)
|
|
4892
|
+
self.containers_selectors["GetCurrentContainer"] = "wa-dialog, wa-message-box,.tmodaldialog, body"
|
|
4893
|
+
container = self.get_current_container()
|
|
4894
|
+
button_candidates = container.select(term_button)
|
|
4895
|
+
|
|
4896
|
+
if button_candidates:
|
|
4897
|
+
filtered_buttons = list(filter(lambda x: hasattr(x, 'caption') and button.lower() in re.sub(regex, '', x['caption'].lower()) and self.element_is_displayed(x), button_candidates))
|
|
4898
|
+
|
|
4899
|
+
if not filtered_buttons:
|
|
4900
|
+
filtered_buttons = self.return_soup_by_selenium(elements=button_candidates, term=button, selectors='label, span')
|
|
4901
|
+
else:
|
|
4902
|
+
footer = self.execute_js_selector('footer', self.soup_to_selenium(container), get_all=False)
|
|
4903
|
+
if footer:
|
|
4904
|
+
footer_buttons = self.execute_js_selector("wa-button", footer)
|
|
4905
|
+
if not footer_buttons:
|
|
4906
|
+
footer_buttons = footer.find_elements(By.CSS_SELECTOR, "wa-button")
|
|
4907
|
+
if footer_buttons:
|
|
4908
|
+
filtered_buttons = list(filter(lambda x: x.text.strip().replace('\n', '') == button.strip().replace(' \n ', ''), footer_buttons))
|
|
4909
|
+
|
|
4910
|
+
# Fallback: botao em foco entre os candidatos
|
|
4911
|
+
if not (filtered_buttons and len(filtered_buttons) - 1 >= position):
|
|
4912
|
+
focus_buttons = list(filter(lambda x: (hasattr(x, 'caption') and button.lower() in re.sub(regex, '', x['caption'].lower())) and 'focus' in x.get('class'), button_candidates))
|
|
4913
|
+
if focus_buttons:
|
|
4914
|
+
filtered_buttons = focus_buttons
|
|
4915
|
+
|
|
4916
|
+
# Fallback: busca ampla via web_scrap
|
|
4917
|
+
if not filtered_buttons:
|
|
4918
|
+
filtered_buttons = self.web_scrap(term=button, scrap_type=enum.ScrapType.MIXED, optional_term="wa-button", main_container=self.containers_selectors["SetButton"])
|
|
4919
|
+
|
|
4920
|
+
if filtered_buttons and len(filtered_buttons) - 1 >= position:
|
|
4921
|
+
parents_actives = list(filter(lambda x: self.filter_active_tabs(x), filtered_buttons))
|
|
4922
|
+
if parents_actives:
|
|
4923
|
+
filtered_buttons = parents_actives
|
|
4924
|
+
next_button = filtered_buttons[position]
|
|
4925
|
+
|
|
4926
|
+
return next_button
|
|
4927
|
+
|
|
4865
4928
|
def SetButton(self, button, sub_item="", position=1, check_error=True):
|
|
4866
4929
|
"""
|
|
4867
4930
|
Method that clicks on a button on the screen.
|
|
@@ -4935,42 +4998,10 @@ class WebappInternal(Base):
|
|
|
4935
4998
|
logger().debug(f"***System Info*** Before Clicking on button:{button}")
|
|
4936
4999
|
system_info()
|
|
4937
5000
|
|
|
4938
|
-
regex = r"(<[^>]*>)?"
|
|
4939
|
-
filtered_button = []
|
|
4940
5001
|
next_button = None
|
|
4941
5002
|
while(time.time() < endtime and not soup_element):
|
|
4942
5003
|
if self.webapp_shadowroot():
|
|
4943
|
-
self.
|
|
4944
|
-
self.containers_selectors["GetCurrentContainer"] = "wa-dialog, wa-message-box,.tmodaldialog, body"
|
|
4945
|
-
soup = self.get_current_container()
|
|
4946
|
-
soup_objects = soup.select(term_button)
|
|
4947
|
-
|
|
4948
|
-
if soup_objects and not filtered_button:
|
|
4949
|
-
filtered_button = list(filter(lambda x: hasattr(x,'caption') and button.lower() in re.sub(regex,'',x['caption'].lower()) and self.element_is_displayed(x), soup_objects ))
|
|
4950
|
-
|
|
4951
|
-
if not filtered_button:
|
|
4952
|
-
filtered_button = self.return_soup_by_selenium(elements=soup_objects, term=button, selectors='label, span')
|
|
4953
|
-
|
|
4954
|
-
if self.webapp_shadowroot():
|
|
4955
|
-
if not soup_objects:
|
|
4956
|
-
footer = self.execute_js_selector('footer', self.soup_to_selenium(soup), get_all=False)
|
|
4957
|
-
if footer:
|
|
4958
|
-
buttons = self.execute_js_selector("wa-button", footer)
|
|
4959
|
-
if not buttons:
|
|
4960
|
-
buttons = footer.find_elements(By.CSS_SELECTOR, "wa-button")
|
|
4961
|
-
if buttons:
|
|
4962
|
-
filtered_button = list(filter(lambda x: x.text.strip().replace('\n', '') == button.strip().replace(' \n ', ''), buttons))
|
|
4963
|
-
|
|
4964
|
-
if filtered_button and len(filtered_button) - 1 >= position:
|
|
4965
|
-
parents_actives = list(filter(lambda x: self.filter_active_tabs(x), filtered_button ))
|
|
4966
|
-
if parents_actives:
|
|
4967
|
-
filtered_button = parents_actives
|
|
4968
|
-
next_button = filtered_button[position]
|
|
4969
|
-
else:
|
|
4970
|
-
filtered_button = list(filter(lambda x: (hasattr(x,'caption') and button.lower() in re.sub(regex,'',x['caption'].lower())) and 'focus' in x.get('class'), soup_objects ))
|
|
4971
|
-
|
|
4972
|
-
if not filtered_button:
|
|
4973
|
-
filtered_button = self.web_scrap(term=button, scrap_type=enum.ScrapType.MIXED, optional_term="wa-button", main_container = self.containers_selectors["SetButton"])
|
|
5004
|
+
next_button = self.get_shadowroot_button(button, term_button, position, check_error)
|
|
4974
5005
|
|
|
4975
5006
|
if next_button:
|
|
4976
5007
|
id_parent_element = next_button['id'] if hasattr(next_button, 'id') and type(next_button) == Tag else None
|
|
@@ -5056,16 +5087,64 @@ class WebappInternal(Base):
|
|
|
5056
5087
|
initial_layers = self.check_layers(".tmodaldialog, wa-dialog, wa-message-box, .ui-dialog")
|
|
5057
5088
|
popup_before = self.check_layers(".tmenupopupitem, wa-menu-popup")
|
|
5058
5089
|
|
|
5059
|
-
# Configurações de retry (fixas, sem novos parâmetros)
|
|
5060
5090
|
max_click_attempts = 3
|
|
5061
5091
|
click_attempt = 0
|
|
5062
5092
|
click_verified = False
|
|
5093
|
+
recaptured = False
|
|
5094
|
+
# Primeira metade do time_out para a captura inicial; se o clique não for
|
|
5095
|
+
# verificado até aqui, recaptura o botão (container já atualizado após a
|
|
5096
|
+
# transição) e usa a metade restante.
|
|
5097
|
+
half_time = starttime + (self.config.time_out / 2)
|
|
5098
|
+
while not click_verified and (click_attempt < max_click_attempts or time.time() < endtime):
|
|
5099
|
+
# Recaptura única, no meio do time_out, quando o clique ainda não foi
|
|
5100
|
+
# verificado — evita reutilizar um soup_element obsoleto capturado da
|
|
5101
|
+
# tela anterior durante uma transição.
|
|
5102
|
+
if not recaptured and time.time() >= half_time:
|
|
5103
|
+
logger().debug(
|
|
5104
|
+
f" [RECAPTURE] Click on '{button}' not verified within first half of time_out; "
|
|
5105
|
+
f"recapturing element (container may have changed after transition)"
|
|
5106
|
+
)
|
|
5107
|
+
new_element, new_restore_zoom = self.recapture_setbutton_element(button, term_button, position, check_error)
|
|
5108
|
+
if new_element is not None:
|
|
5109
|
+
soup_element = new_element
|
|
5110
|
+
restore_zoom = new_restore_zoom
|
|
5111
|
+
try:
|
|
5112
|
+
button_element_id = soup_element.get_attribute('id') or 'unknow'
|
|
5113
|
+
except Exception:
|
|
5114
|
+
button_element_id = 'unknow'
|
|
5115
|
+
logger().debug(f" [RECAPTURE] New element captured (id: {button_element_id})")
|
|
5116
|
+
else:
|
|
5117
|
+
logger().warning(f" [RECAPTURE] Could not recapture '{button}'; keeping previously captured element")
|
|
5118
|
+
recaptured = True
|
|
5119
|
+
|
|
5120
|
+
# Rebaseline do estado pré-clique após a transição, para que os
|
|
5121
|
+
# checks de verificação existentes comparem contra o estado correto.
|
|
5122
|
+
container_before_click = self.get_current_container()
|
|
5123
|
+
if container_before_click and 'id' in container_before_click.attrs:
|
|
5124
|
+
initial_container_id = container_before_click.attrs['id']
|
|
5125
|
+
initial_dom_hash = hash(str(self.get_current_DOM()))
|
|
5126
|
+
skip_focus_retry = True
|
|
5127
|
+
container_texts_before = self.get_current_container_texts()
|
|
5128
|
+
df_before, grids_on_screen_before = self.grid_dataframe(grid_number=0, wait=False, check_error=False, current_container=True, throw_error=False)
|
|
5129
|
+
rows = []
|
|
5130
|
+
rows_box_state_before = []
|
|
5131
|
+
if grids_on_screen_before:
|
|
5132
|
+
rows = self.execute_js_selector('tr', self.soup_to_selenium(grids_on_screen_before))
|
|
5133
|
+
if rows:
|
|
5134
|
+
rows_box_state_before = list(map(lambda x: self.get_row_divs_style(x), rows))
|
|
5135
|
+
initial_layers = self.check_layers(".tmodaldialog, wa-dialog, wa-message-box, .ui-dialog")
|
|
5136
|
+
popup_before = self.check_layers(".tmenupopupitem, wa-menu-popup")
|
|
5063
5137
|
|
|
5064
|
-
while click_attempt < max_click_attempts and not click_verified:
|
|
5065
5138
|
click_attempt += 1
|
|
5139
|
+
# Estratégia progressiva: avança ao longo das iterações do laço e NÃO
|
|
5140
|
+
# reinicia na recaptura; após a última, mantém a mais robusta (JS).
|
|
5141
|
+
strategy_index = min(click_attempt - 1, max_click_attempts - 1)
|
|
5066
5142
|
current_clicked_element = None
|
|
5067
5143
|
|
|
5068
|
-
logger().debug(
|
|
5144
|
+
logger().debug(
|
|
5145
|
+
f"Click attempt {click_attempt} (strategy {strategy_index}, recaptured={recaptured}) "
|
|
5146
|
+
f"on '{button}' (id: {button_element_id} in container: {initial_container_id})"
|
|
5147
|
+
)
|
|
5069
5148
|
|
|
5070
5149
|
if self.webapp_shadowroot():
|
|
5071
5150
|
self.scroll_to_element(soup_element)
|
|
@@ -5075,9 +5154,9 @@ class WebappInternal(Base):
|
|
|
5075
5154
|
# Small delay to ensure stability (avoids clicking during transitions)
|
|
5076
5155
|
time.sleep(0.5)
|
|
5077
5156
|
|
|
5078
|
-
if
|
|
5157
|
+
if strategy_index == 0:
|
|
5079
5158
|
self.send_action(action=self.click, element=lambda: soup_element)
|
|
5080
|
-
elif
|
|
5159
|
+
elif strategy_index == 1:
|
|
5081
5160
|
logger().debug(" |-- Using ActionChains for greater robustness")
|
|
5082
5161
|
self.click(soup_element, click_type=enum.ClickType.ACTIONCHAINS)
|
|
5083
5162
|
else:
|
|
@@ -5204,7 +5283,7 @@ class WebappInternal(Base):
|
|
|
5204
5283
|
except Exception:
|
|
5205
5284
|
pass
|
|
5206
5285
|
|
|
5207
|
-
if not click_verified
|
|
5286
|
+
if not click_verified:
|
|
5208
5287
|
logger().warning(f" [WARN] Click on '{button}' had no detectable effect on attempt {click_attempt}")
|
|
5209
5288
|
time.sleep(0.5)
|
|
5210
5289
|
|
|
@@ -5213,7 +5292,7 @@ class WebappInternal(Base):
|
|
|
5213
5292
|
logger().debug(f"Container after click '{button}': {current_container_id}")
|
|
5214
5293
|
|
|
5215
5294
|
if not click_verified:
|
|
5216
|
-
logger().warning(f" [WARN] Click on '{button}' may not have been effective after {
|
|
5295
|
+
logger().warning(f" [WARN] Click on '{button}' may not have been effective after {click_attempt} attempts (recaptured={recaptured}). Continuing execution...")
|
|
5217
5296
|
|
|
5218
5297
|
if sub_item and ',' not in sub_item:
|
|
5219
5298
|
logger().info(f"Clicking on {sub_item}")
|
|
@@ -5317,6 +5396,54 @@ class WebappInternal(Base):
|
|
|
5317
5396
|
self.reset_container_position()
|
|
5318
5397
|
|
|
5319
5398
|
|
|
5399
|
+
def recapture_setbutton_element(self, button, term_button, position, check_error=True):
|
|
5400
|
+
"""
|
|
5401
|
+
[Internal]
|
|
5402
|
+
|
|
5403
|
+
Re-captures the SetButton target element using the same capture logic as the
|
|
5404
|
+
initial capture in :meth:`SetButton` (respecting ``webapp_shadowroot()``,
|
|
5405
|
+
``restore_zoom``, ``position`` and ``element_is_displayed`` filtering, with the
|
|
5406
|
+
fallback without ``filter_blocked_containers``).
|
|
5407
|
+
|
|
5408
|
+
This is used by ``SetButton`` when the initial single capture may have grabbed a
|
|
5409
|
+
stale element from the previous container during a screen transition. After the
|
|
5410
|
+
transition completes the container is already updated, so recapturing returns the
|
|
5411
|
+
correct element.
|
|
5412
|
+
|
|
5413
|
+
:return: Tuple ``(soup_element, restore_zoom)``. ``soup_element`` is a Selenium
|
|
5414
|
+
element (or ``None`` when not found) and ``restore_zoom`` indicates that a
|
|
5415
|
+
zoom-out was applied to make the element visible.
|
|
5416
|
+
:rtype: tuple
|
|
5417
|
+
"""
|
|
5418
|
+
soup_element = None
|
|
5419
|
+
restore_zoom = False
|
|
5420
|
+
try:
|
|
5421
|
+
if self.webapp_shadowroot():
|
|
5422
|
+
next_button = self.get_shadowroot_button(button, term_button, position, check_error)
|
|
5423
|
+
if next_button:
|
|
5424
|
+
soup_element = self.soup_to_selenium(next_button) if type(next_button) == Tag else next_button
|
|
5425
|
+
if soup_element is not None:
|
|
5426
|
+
self.scroll_to_element(soup_element)
|
|
5427
|
+
soup_element = soup_element if self.element_is_displayed(soup_element) else None
|
|
5428
|
+
if soup_element is None and next_button is not None:
|
|
5429
|
+
bodySoup = self.get_current_DOM().select('body')
|
|
5430
|
+
self.driver.execute_script("arguments[0].style.cssText+='transform: scale(0.8)';", self.soup_to_selenium(bodySoup[0]))
|
|
5431
|
+
soup_element = self.soup_to_selenium(next_button) if type(next_button) == Tag else next_button
|
|
5432
|
+
soup_element = soup_element if self.element_is_displayed(soup_element) else None
|
|
5433
|
+
restore_zoom = True
|
|
5434
|
+
else:
|
|
5435
|
+
soup_objects = self.web_scrap(term=button, scrap_type=enum.ScrapType.MIXED, optional_term="button, .thbutton", main_container=self.containers_selectors["SetButton"], check_error=check_error)
|
|
5436
|
+
if isinstance(soup_objects, list):
|
|
5437
|
+
soup_objects = list(filter(lambda x: self.element_is_displayed(x), soup_objects))
|
|
5438
|
+
if soup_objects and len(soup_objects) - 1 >= position:
|
|
5439
|
+
self.wait_until_to(expected_condition="element_to_be_clickable", element=soup_objects[position], locator=By.XPATH, timeout=True)
|
|
5440
|
+
soup_element = self.soup_to_selenium(soup_objects[position])
|
|
5441
|
+
except Exception as e:
|
|
5442
|
+
logger().debug(f"Recapture of button '{button}' failed: {e}")
|
|
5443
|
+
soup_element = None
|
|
5444
|
+
return soup_element, restore_zoom
|
|
5445
|
+
|
|
5446
|
+
|
|
5320
5447
|
def get_current_container_texts(self):
|
|
5321
5448
|
"""This method returns a list of all texts from current container descendents
|
|
5322
5449
|
"""
|
|
@@ -7409,7 +7536,7 @@ class WebappInternal(Base):
|
|
|
7409
7536
|
cell_filled = self.select_combo(selenium_input(), user_value)
|
|
7410
7537
|
time.sleep(1)
|
|
7411
7538
|
# if modal opened close it
|
|
7412
|
-
if current_layers()
|
|
7539
|
+
if current_layers() == initial_layers + 1:
|
|
7413
7540
|
self.send_keys(selenium_column, Keys.TAB)
|
|
7414
7541
|
else:
|
|
7415
7542
|
if cell_opened:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.14.3'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.14.2'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/linux64/geckodriver
RENAMED
|
File without changes
|
{tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/windows/chromedriver.exe
RENAMED
|
File without changes
|
|
File without changes
|
{tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/drivers/windows/geckodriver.exe
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/third_party/screen_size.py
RENAMED
|
File without changes
|
{tir_framework-2.14.2 → tir_framework-2.14.3}/tir/technologies/core/third_party/xpath_soup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|