cucu 1.2.2__tar.gz → 1.2.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.

Potentially problematic release.


This version of cucu might be problematic. Click here for more details.

Files changed (94) hide show
  1. {cucu-1.2.2 → cucu-1.2.3}/CHANGELOG.md +3 -0
  2. {cucu-1.2.2 → cucu-1.2.3}/PKG-INFO +1 -1
  3. {cucu-1.2.2 → cucu-1.2.3}/pyproject.toml +1 -1
  4. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/browser/core.py +12 -0
  5. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/browser/selenium.py +46 -0
  6. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/environment.py +6 -6
  7. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/browser_steps.py +64 -2
  8. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/utils.py +0 -13
  9. {cucu-1.2.2 → cucu-1.2.3}/.gitignore +0 -0
  10. {cucu-1.2.2 → cucu-1.2.3}/LICENSE +0 -0
  11. {cucu-1.2.2 → cucu-1.2.3}/README.md +0 -0
  12. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/__init__.py +0 -0
  13. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/ansi_parser.py +0 -0
  14. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/behave_tweaks.py +0 -0
  15. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/browser/__init__.py +0 -0
  16. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/browser/frames.py +0 -0
  17. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/browser/selenium_tweaks.py +0 -0
  18. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/cli/__init__.py +0 -0
  19. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/cli/core.py +0 -0
  20. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/cli/run.py +0 -0
  21. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/cli/steps.py +0 -0
  22. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/cli/thread_dumper.py +0 -0
  23. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/config.py +0 -0
  24. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/edgedriver_autoinstaller/README.md +0 -0
  25. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/edgedriver_autoinstaller/__init__.py +0 -0
  26. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/edgedriver_autoinstaller/utils.py +0 -0
  27. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/external/jquery/jquery-3.5.1.min.js +0 -0
  28. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/formatter/__init__.py +0 -0
  29. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/formatter/cucu.py +0 -0
  30. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/formatter/json.py +0 -0
  31. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/formatter/junit.py +0 -0
  32. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/fuzzy/__init__.py +0 -0
  33. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/fuzzy/core.py +0 -0
  34. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/fuzzy/fuzzy.js +0 -0
  35. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/helpers.py +0 -0
  36. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/hooks.py +0 -0
  37. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/.gitignore +0 -0
  38. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/README.md +0 -0
  39. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/cucurc.yml +0 -0
  40. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/data/www/example.html +0 -0
  41. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/features/cucurc.yml +0 -0
  42. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/features/environment.py +0 -0
  43. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/features/example.feature +0 -0
  44. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/features/lint_rules/sid.yaml +0 -0
  45. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/features/steps/__init__.py +0 -0
  46. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/init_data/features/steps/my_steps.py +0 -0
  47. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/language_server/__init__.py +0 -0
  48. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/language_server/core.py +0 -0
  49. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/lint/__init__.py +0 -0
  50. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/lint/linter.py +0 -0
  51. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/lint/rules/format.yaml +0 -0
  52. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/logger.py +0 -0
  53. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/matcher/__init__.py +0 -0
  54. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/matcher/core.py +0 -0
  55. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/page_checks.py +0 -0
  56. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/__init__.py +0 -0
  57. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/bootstrap.min.css +0 -0
  58. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/bootstrap.min.js +0 -0
  59. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/dataTables.bootstrap.min.css +0 -0
  60. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/dataTables.bootstrap.min.js +0 -0
  61. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/jquery-3.5.1.min.js +0 -0
  62. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/jquery.dataTables.min.js +0 -0
  63. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/external/popper.min.js +0 -0
  64. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/favicon.png +0 -0
  65. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/html.py +0 -0
  66. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/templates/feature.html +0 -0
  67. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/templates/flat.html +0 -0
  68. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/templates/index.html +0 -0
  69. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/templates/layout.html +0 -0
  70. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/reporter/templates/scenario.html +0 -0
  71. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/__init__.py +0 -0
  72. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/base_steps.py +0 -0
  73. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/button_steps.py +0 -0
  74. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/checkbox_steps.py +0 -0
  75. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/command_steps.py +0 -0
  76. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/draggable_steps.py +0 -0
  77. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/dropdown_steps.py +0 -0
  78. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/file_input_steps.py +0 -0
  79. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/filesystem_steps.py +0 -0
  80. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/flow_control_steps.py +0 -0
  81. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/image_steps.py +0 -0
  82. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/input_steps.py +0 -0
  83. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/link_steps.py +0 -0
  84. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/menuitem_steps.py +0 -0
  85. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/platform_steps.py +0 -0
  86. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/radio_steps.py +0 -0
  87. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/section_steps.py +0 -0
  88. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/step_utils.py +0 -0
  89. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/tab_steps.py +0 -0
  90. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/table_steps.py +0 -0
  91. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/tables.js +0 -0
  92. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/text_steps.py +0 -0
  93. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/variable_steps.py +0 -0
  94. {cucu-1.2.2 → cucu-1.2.3}/src/cucu/steps/webserver_steps.py +0 -0
@@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project closely adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 1.2.3
9
+ - Add - additional tab information steps
10
+ - Change - retry open a browser
8
11
 
9
12
  ## 1.2.2
10
13
  - Chore - make lint also run ruff format --check
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cucu
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Easy BDD web testing
5
5
  Project-URL: Homepage, https://github.com/dominodatalab/cucu/wiki
6
6
  Project-URL: Download, https://pypi.org/project/cucu/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cucu"
3
- version = "1.2.2"
3
+ version = "1.2.3"
4
4
  description = "Easy BDD web testing"
5
5
  readme = "README.md"
6
6
  license = { text = "The Clear BSD License" }
@@ -55,6 +55,18 @@ class Browser:
55
55
  def close_window(self):
56
56
  raise RuntimeError("implement me")
57
57
 
58
+ def get_tab_info(self):
59
+ raise RuntimeError("implement me")
60
+
61
+ def get_all_tabs_info(self):
62
+ raise RuntimeError("implement me")
63
+
64
+ def switch_to_nth_tab(self, tab_index):
65
+ raise RuntimeError("implement me")
66
+
67
+ def switch_to_tab_that_matches_regex(self, text):
68
+ raise RuntimeError("implement me")
69
+
58
70
  def quit(self):
59
71
  raise RuntimeError("implement me")
60
72
 
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import os
3
+ import re
3
4
 
4
5
  import chromedriver_autoinstaller
5
6
  import geckodriver_autoinstaller
@@ -226,6 +227,51 @@ class Selenium(Browser):
226
227
  raise RuntimeError("no previous browser tab available")
227
228
  self.driver.switch_to.window(window_handles[window_handle_index - 1])
228
229
 
230
+ def switch_to_nth_tab(self, tab_number):
231
+ print(f"tab_number, {tab_number}")
232
+ window_handles = self.driver.window_handles
233
+ total_tabs = len(window_handles)
234
+ if tab_number > total_tabs:
235
+ raise RuntimeError(f"no {tab_number} browser tab available")
236
+ self.driver.switch_to.window(window_handles[tab_number])
237
+
238
+ def switch_to_tab_that_matches_regex(self, title_pattern):
239
+ window_handles = self.driver.window_handles
240
+
241
+ for handle in window_handles:
242
+ self.driver.switch_to.window(handle)
243
+ if re.search(title_pattern, self.driver.title):
244
+ return
245
+
246
+ raise Exception(f"No tab title matches pattern: {title_pattern}")
247
+
248
+ def get_tab_info(self):
249
+ window_handles = self.driver.window_handles
250
+ current_window = self.driver.current_window_handle
251
+ window_handle_index = window_handles.index(current_window)
252
+
253
+ return {
254
+ "tab_count": len(window_handles),
255
+ "index": window_handle_index,
256
+ "title": self.driver.title,
257
+ "url": self.driver.current_url,
258
+ }
259
+
260
+ def get_all_tabs_info(self):
261
+ tabs_info = []
262
+ handles = self.driver.window_handles
263
+ for idx, handle in enumerate(handles):
264
+ self.driver.switch_to.window(handle)
265
+ tabs_info.append(
266
+ {
267
+ "index": idx,
268
+ "title": self.driver.title,
269
+ "url": self.driver.current_url,
270
+ }
271
+ )
272
+
273
+ return tabs_info
274
+
229
275
  def back(self):
230
276
  self.driver.back()
231
277
  self.wait_for_page_to_load()
@@ -10,7 +10,7 @@ from functools import partial
10
10
  from cucu import config, init_scenario_hook_variables, logger
11
11
  from cucu.config import CONFIG
12
12
  from cucu.page_checks import init_page_checks
13
- from cucu.utils import ellipsize_filename, get_tab_information, take_screenshot
13
+ from cucu.utils import ellipsize_filename, take_screenshot
14
14
 
15
15
  CONFIG.define(
16
16
  "FEATURE_RESULTS_DIR",
@@ -264,11 +264,11 @@ def after_step(ctx, step):
264
264
  if ctx.browser is not None and ctx.current_step.has_substeps is False:
265
265
  take_screenshot(ctx, step.name, label=f"After {step.name}")
266
266
 
267
- tab_info = get_tab_information(ctx)
268
- total_tabs = tab_info["window_count"]
269
- current_tab = tab_info["current_index"] + 1
270
- title = tab_info["current_title"]
271
- url = tab_info["current_url"]
267
+ tab_info = ctx.browser.get_tab_info()
268
+ total_tabs = tab_info["tab_count"]
269
+ current_tab = tab_info["index"] + 1
270
+ title = tab_info["title"]
271
+ url = tab_info["url"]
272
272
  log_message = (
273
273
  f"\ntab({current_tab} of {total_tabs}): {title}\nurl: {url}\n"
274
274
  )
@@ -32,7 +32,7 @@ def open_a_browser(ctx, url):
32
32
  Given I open a browser at the url "https://www.google.com"
33
33
  """
34
34
  if ctx.browser is None:
35
- ctx.browser = open_browser(ctx)
35
+ ctx.browser = retry(open_browser)(ctx)
36
36
  ctx.browsers.append(ctx.browser)
37
37
  else:
38
38
  logger.debug("browser already open so using existing instance")
@@ -43,7 +43,7 @@ def open_a_browser(ctx, url):
43
43
 
44
44
  @step('I open a new browser at the url "{url}"')
45
45
  def open_a_new_browser(ctx, url):
46
- ctx.browser = open_browser(ctx)
46
+ ctx.browser = retry(open_browser)(ctx)
47
47
  ctx.browsers.append(ctx.browser)
48
48
  logger.debug(f"navigating to url #{url}")
49
49
  ctx.browser.navigate(url)
@@ -219,6 +219,68 @@ def wait_to_switch_to_previous_browser_tab(ctx):
219
219
  retry(switch_to_previous_tab)(ctx)
220
220
 
221
221
 
222
+ def switch_to_nth_tab(ctx, tab_number):
223
+ ctx.check_browser_initialized()
224
+ ctx.browser.switch_to_nth_tab(tab_number)
225
+
226
+
227
+ @step('I switch to the "{nth:nth}" browser tab')
228
+ def switch_to_nth_browser_tab(ctx, nth):
229
+ switch_to_nth_tab(ctx, nth)
230
+
231
+
232
+ @step('I wait to switch to the "{nth:nth}" browser tab')
233
+ def wait_to_switch_to_nth_browser_tab(ctx, nth):
234
+ retry(switch_to_nth_tab)(ctx, nth)
235
+
236
+
237
+ def switch_to_tab_matching_regex(ctx, regex):
238
+ ctx.check_browser_initialized()
239
+ ctx.browser.switch_to_tab_that_matches_regex(regex)
240
+
241
+
242
+ @step('I switch to the browser tab that matches "{regex}"')
243
+ def switch_to_browser_tab_matching_regex(ctx, regex):
244
+ switch_to_tab_matching_regex(ctx, regex)
245
+
246
+
247
+ @step('I wait to switch to the browser tab that matches "{regex}"')
248
+ def wait_to_switch_to_browser_tab_matching_regex(ctx, regex):
249
+ retry(switch_to_tab_matching_regex)(ctx, regex)
250
+
251
+
252
+ @step('I save the browser tabs info to the variable "{variable}"')
253
+ def save_browser_tabs_info_to_variable(ctx, variable):
254
+ ctx.check_browser_initialized()
255
+ tabs_info = ctx.browser.get_all_tabs_info()
256
+ lst_tab_info = [
257
+ f"tab({tab['index'] + 1}): {tab['title']}, url: {tab['url']}"
258
+ for tab in tabs_info
259
+ ]
260
+ config.CONFIG[variable] = lst_tab_info
261
+
262
+
263
+ @step("I list the current browser tab info")
264
+ def list_current_browser_tab_info(ctx):
265
+ ctx.check_browser_initialized()
266
+ tab_info = ctx.browser.get_tab_info()
267
+ current_tab = tab_info["index"] + 1
268
+ title = tab_info["title"]
269
+ url = tab_info["url"]
270
+ print(f"\ntab({current_tab}): {title}\nurl: {url}\n")
271
+
272
+
273
+ @step("I list all browser tabs info")
274
+ def list_browser_tabs_info(ctx):
275
+ ctx.check_browser_initialized()
276
+ all_tabs_info = ctx.browser.get_all_tabs_info()
277
+ for tab in all_tabs_info:
278
+ tab_index = tab["index"] + 1
279
+ title = tab["title"]
280
+ url = tab["url"]
281
+ print(f"\ntab({tab_index}): {title}\nurl: {url}\n")
282
+
283
+
222
284
  def save_downloaded_file(ctx, filename):
223
285
  ctx.check_browser_initialized()
224
286
 
@@ -274,19 +274,6 @@ def take_screenshot(ctx, step_name, label="", element=None):
274
274
  CONFIG["__STEP_SCREENSHOT_COUNT"] += 1
275
275
 
276
276
 
277
- def get_tab_information(ctx):
278
- driver = ctx.browser.driver
279
- window_handles = driver.window_handles
280
- current_window = driver.current_window_handle
281
- window_handle_index = window_handles.index(current_window)
282
- return {
283
- "window_count": len(window_handles),
284
- "current_index": window_handle_index,
285
- "current_title": driver.title,
286
- "current_url": driver.current_url,
287
- }
288
-
289
-
290
277
  def find_n_click_input_parent_label(ctx, input_element):
291
278
  """
292
279
  Clicks the nearest parent <label> of an input elemnt (if input is visually hidden or size is zero).
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
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
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
File without changes
File without changes
File without changes