cucu 1.1.2__py3-none-any.whl → 1.2.1__py3-none-any.whl

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.

cucu/behave_tweaks.py CHANGED
@@ -66,7 +66,9 @@ def init_step_hooks(stdout, stderr):
66
66
  # resolve variables in the table values
67
67
  if ctx.table is not None:
68
68
  ctx.table.original = Table(
69
- ctx.table.headings, rows=ctx.table.rows, line=ctx.table.line
69
+ ctx.table.headings,
70
+ rows=ctx.table.rows,
71
+ line=ctx.table.line,
70
72
  )
71
73
  new_rows = []
72
74
  for row in ctx.table.rows:
@@ -123,7 +125,9 @@ def init_step_hooks(stdout, stderr):
123
125
 
124
126
  return wrapper
125
127
 
126
- behave.__dict__[decorator_name.title()] = behave.__dict__[decorator_name] = new_decorator
128
+ behave.__dict__[decorator_name.title()] = behave.__dict__[
129
+ decorator_name
130
+ ] = new_decorator
127
131
 
128
132
 
129
133
  _stdout = sys.stdout
cucu/browser/selenium.py CHANGED
@@ -215,7 +215,6 @@ class Selenium(Browser):
215
215
 
216
216
  if window_handle_index == len(window_handles) - 1:
217
217
  raise RuntimeError("no next browser tab available")
218
-
219
218
  self.driver.switch_to.window(window_handles[window_handle_index + 1])
220
219
 
221
220
  def switch_to_previous_tab(self):
@@ -225,7 +224,6 @@ class Selenium(Browser):
225
224
 
226
225
  if window_handle_index == 0:
227
226
  raise RuntimeError("no previous browser tab available")
228
-
229
227
  self.driver.switch_to.window(window_handles[window_handle_index - 1])
230
228
 
231
229
  def back(self):
cucu/environment.py CHANGED
@@ -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, take_screenshot
13
+ from cucu.utils import ellipsize_filename, get_tab_information, take_screenshot
14
14
 
15
15
  CONFIG.define(
16
16
  "FEATURE_RESULTS_DIR",
@@ -24,7 +24,7 @@ CONFIG.define(
24
24
  )
25
25
  CONFIG.define(
26
26
  "SCENARIO_DOWNLOADS_DIR",
27
- "the browser downloads directory for the currently " "executing scenario",
27
+ "the browser downloads directory for the currently executing scenario",
28
28
  default=None,
29
29
  )
30
30
 
@@ -264,6 +264,21 @@ 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"]
272
+ log_message = (
273
+ f"\ntab({current_tab} of {total_tabs}): {title}\nurl: {url}\n"
274
+ )
275
+ logger.debug(log_message)
276
+
277
+ # Add tab info to step.stdout so it shows up in the HTML report
278
+ step.stdout += (
279
+ f"\ntab({current_tab} of {total_tabs}): {title}\nurl: {url}\n"
280
+ )
281
+
267
282
  # if the step has substeps from using `run_steps` then we already moved
268
283
  # the step index in the run_steps method and shouldn't do it here
269
284
  if not step.has_substeps:
@@ -105,6 +105,15 @@ and_keyword_indented_correctly:
105
105
  match: '^\s*'
106
106
  replace: ' '
107
107
 
108
+ section_step_indented_correctly:
109
+ message: "section step (* #...) should be indented with 8 spaces"
110
+ type: warning
111
+ current_line:
112
+ match: '^(\s{0,7}|\s{9,})\* .*'
113
+ fix:
114
+ match: '^\s*'
115
+ replace: ' '
116
+
108
117
  line_with_extraneous_whitespace:
109
118
  message: line has extraneous whitespace at the end
110
119
  type: warning
cucu/reporter/html.py CHANGED
@@ -199,8 +199,13 @@ def generate(results, basepath, only_failures=False):
199
199
  image_dir = get_step_image_dir(step_index, step["name"])
200
200
  image_dirpath = os.path.join(scenario_filepath, image_dir)
201
201
 
202
+ # Handle section headings with different levels (# to ####)
202
203
  if step["name"].startswith("#"):
203
- step["heading_level"] = "h4"
204
+ # Map the count to the appropriate HTML heading (h2-h5)
205
+ # We use h2-h5 instead of h1-h4 so h1 can be reserved for scenario/feature titles
206
+ step["heading_level"] = (
207
+ f"h{step["name"][:4].count("#") + 1}"
208
+ )
204
209
 
205
210
  if os.path.exists(image_dirpath):
206
211
  _, _, image_names = next(os.walk(image_dirpath))
@@ -51,6 +51,41 @@
51
51
  display: inline;
52
52
  color: gray;
53
53
  }
54
+
55
+ /* Section heading styles */
56
+ h2[style*="display: contents;"] {
57
+ font-size: 1.5em;
58
+ font-weight: bold;
59
+ color: #333;
60
+ border-bottom: 1px solid #ccc;
61
+ margin-top: 10px;
62
+ margin-bottom: 10px;
63
+ }
64
+
65
+ h3[style*="display: contents;"] {
66
+ font-size: 1.3em;
67
+ font-weight: bold;
68
+ color: #444;
69
+ margin-top: 8px;
70
+ margin-bottom: 8px;
71
+ }
72
+
73
+ h4[style*="display: contents;"] {
74
+ font-size: 1.1em;
75
+ font-weight: bold;
76
+ color: #555;
77
+ margin-top: 6px;
78
+ margin-bottom: 6px;
79
+ }
80
+
81
+ h5[style*="display: contents;"] {
82
+ font-size: 1em;
83
+ font-style: italic;
84
+ font-weight: bold;
85
+ color: #666;
86
+ margin-top: 4px;
87
+ margin-bottom: 4px;
88
+ }
54
89
  </style>
55
90
  <script>
56
91
  function setupReportTables(defaultOrder, columns) {
cucu/steps/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # nopycln: file
3
3
  import cucu.hooks
4
4
 
5
- import cucu.steps.comment_steps
5
+ import cucu.steps.section_steps
6
6
  import cucu.steps.base_steps
7
7
 
8
8
  import cucu.steps.browser_steps
@@ -0,0 +1,25 @@
1
+ from behave import use_step_matcher
2
+
3
+ from cucu import step
4
+
5
+ use_step_matcher("re") # use regex to match section heading patterns
6
+
7
+
8
+ @step("(#{1,4})\\s*(.*)")
9
+ def section_step(ctx, heading_level, section_text):
10
+ """
11
+ A section heading step that organizes scenarios into logical sections.
12
+
13
+ Usage:
14
+ * # Main section
15
+ * ## Subsection
16
+ * ### Sub-subsection
17
+ * #### Deep subsection
18
+
19
+ The number of # characters determines the heading level (1-4).
20
+ This step is a no-op but provides structure in the HTML report.
21
+ """
22
+ pass
23
+
24
+
25
+ use_step_matcher("parse") # set this back to cucu's default matcher parser
cucu/utils.py CHANGED
@@ -271,3 +271,16 @@ def take_screenshot(ctx, step_name, label="", element=None):
271
271
  shutil.copyfile(filepath, CONFIG["CUCU_MONITOR_PNG"])
272
272
 
273
273
  CONFIG["__STEP_SCREENSHOT_COUNT"] += 1
274
+
275
+
276
+ def get_tab_information(ctx):
277
+ driver = ctx.browser.driver
278
+ window_handles = driver.window_handles
279
+ current_window = driver.current_window_handle
280
+ window_handle_index = window_handles.index(current_window)
281
+ return {
282
+ "window_count": len(window_handles),
283
+ "current_index": window_handle_index,
284
+ "current_title": driver.title,
285
+ "current_url": driver.current_url,
286
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cucu
3
- Version: 1.1.2
3
+ Version: 1.2.1
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/
@@ -16,20 +16,12 @@ Classifier: Intended Audience :: Developers
16
16
  Classifier: License :: OSI Approved :: BSD License
17
17
  Classifier: Natural Language :: English
18
18
  Classifier: Operating System :: OS Independent
19
- Classifier: Programming Language :: Python
20
- Classifier: Programming Language :: Python :: 3
21
- Classifier: Programming Language :: Python :: 3 :: Only
22
- Classifier: Programming Language :: Python :: 3.9
23
- Classifier: Programming Language :: Python :: 3.10
24
- Classifier: Programming Language :: Python :: 3.11
25
- Classifier: Programming Language :: Python :: 3.12
26
- Classifier: Programming Language :: Python :: 3.13
27
19
  Classifier: Topic :: Software Development :: Testing :: BDD
28
- Requires-Python: >=3.9
20
+ Requires-Python: >=3.10
29
21
  Requires-Dist: beautifulsoup4~=4.13.3
30
22
  Requires-Dist: behave==1.2.6
31
23
  Requires-Dist: chromedriver-autoinstaller~=0.6.2
32
- Requires-Dist: click~=8.1.7
24
+ Requires-Dist: click~=8.2.0
33
25
  Requires-Dist: coverage[toml]~=7.8
34
26
  Requires-Dist: geckodriver-autoinstaller~=0.1.0
35
27
  Requires-Dist: humanize~=4.12.1
@@ -1,17 +1,17 @@
1
1
  cucu/__init__.py,sha256=YtuajsJBj3_DgNoygHen9gKojeQF523Oc27kyCUzoG0,1013
2
2
  cucu/ansi_parser.py,sha256=_yTlqr6KruLsqgWR6BkpJUC3bmlQy_9JbkuxFx6Jrbo,2213
3
- cucu/behave_tweaks.py,sha256=SfI1GVefiihdcJSZI4WLawYToTgTS_bv-TlXuw8Q4rw,6794
3
+ cucu/behave_tweaks.py,sha256=MqIL9BDHMvmyXyzkVGbD3wd8IP38_8pgp3NPGDWudm8,6873
4
4
  cucu/config.py,sha256=12SXNtBSnD3N6K9DnCDYHZDA4_Wrh4g7whdgHDKSuPw,14022
5
- cucu/environment.py,sha256=n5FyAq2T8t_dl1YdM38Wdp6yx9h0bL0pHyP5mAlhl00,9429
5
+ cucu/environment.py,sha256=Glhs2Gq2YGHYaIbhozljZse9Q2QkXK0jzPxnychBLGU,9996
6
6
  cucu/helpers.py,sha256=l_YMmbuXjtBRo-MER-qe6soUIyjt0ey2BoSgWs4zYwA,36285
7
7
  cucu/hooks.py,sha256=3Z1mavU42XMQ0DZ7lVWwTB-BJYHRyYUOzzOtmkdIsow,7117
8
8
  cucu/logger.py,sha256=Y4eHmNFCphqXEzUQD-DJ8dsaqTNtqxmaKSCdo66Oc-g,3349
9
9
  cucu/page_checks.py,sha256=CW1AqIxZ7rrLxpkf8nEFwcw6amnoN3Tb-acoN8dq3g0,2179
10
- cucu/utils.py,sha256=608b28WVWgzmFMAMLXpFWeXe3NjRZEhpEfcTnYy2JRM,8611
10
+ cucu/utils.py,sha256=gLeVT9Vo7rBwCXMVUzhhex854NjCFy05rUDDGG23mqY,9023
11
11
  cucu/browser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  cucu/browser/core.py,sha256=YAHhj6AMf7kpZR57thQaPHVHVHwnMBzCI0yofIYtfaY,2355
13
13
  cucu/browser/frames.py,sha256=IW7kzRJn5PkbMaovIelAeCWO-T-2sOTwqaYBw-0-LKU,3545
14
- cucu/browser/selenium.py,sha256=IOLzSyxNDUxEccc10qXV8hf817hNgUBRCHz1PbCEKhs,11605
14
+ cucu/browser/selenium.py,sha256=oyXnf8jNPX3EqvaFYDhZuxoxGnK8cw__7CxMZTG1hfU,11603
15
15
  cucu/browser/selenium_tweaks.py,sha256=oUIhWVhBZbc9qsmQUJMpIr9uUWKxtgZBcnySWU6Yttk,879
16
16
  cucu/cli/__init__.py,sha256=uXX5yVG1konJ_INdlrcfMg-Tt_5_cSx29Ed8R8v908A,62
17
17
  cucu/cli/core.py,sha256=Lh6kRFuzQkuPo01oYfZNedn6PM4F4p1qtUKgDwh4K1I,25334
@@ -43,12 +43,12 @@ cucu/language_server/__init__.py,sha256=IUO7FXpRDgvEmljSuB_WpT_BoBRdgG7lhTBFWUwm
43
43
  cucu/language_server/core.py,sha256=mUCdkk484ldlXRC7hQmLKXGnQ37NumwuERqNZEyCUN4,3532
44
44
  cucu/lint/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
45
  cucu/lint/linter.py,sha256=EeeU9DHL4s2MJDglJb1m8wXv4uolY7XAgfgnLY1Hqh8,13246
46
- cucu/lint/rules/format.yaml,sha256=1OxJrHjzquGo_BHNp6qH9Cc3-QU0XIYEuGKt64vqLxM,2949
46
+ cucu/lint/rules/format.yaml,sha256=Gm7Mx_KnL6s8EOyKGtZZBgREJPrviv-FuYzya3tyV_E,3168
47
47
  cucu/matcher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
48
  cucu/matcher/core.py,sha256=o2j4NNGORZ0BtHEbBTeE2T_vi6EJlWVkrjOoS2L7UNk,1032
49
49
  cucu/reporter/__init__.py,sha256=nS2lIp43gifspIDgieSS3dzBMvnKfd--O8Pb3RTr4yE,71
50
50
  cucu/reporter/favicon.png,sha256=9ikXLAmzfQzy2NQps_8CGaZog2FvQrOX8nnSZ0e1UmM,2161
51
- cucu/reporter/html.py,sha256=a6Djq9xKP16OVQ0QADuoQGpUpfYU0TfFEmja7PjSs1Y,16344
51
+ cucu/reporter/html.py,sha256=JOSLkUCARJ7kbhe7LAhbWeZh_ujiHU_a6ke7MHgpjIk,16679
52
52
  cucu/reporter/external/bootstrap.min.css,sha256=eHMy9CG2IWZObUwZAkNVWc6DTIds3OavzUguDY0VsIo,163874
53
53
  cucu/reporter/external/bootstrap.min.js,sha256=eZoFcnJ9Ooanw0yPsrZ3CHiXIYUBW-7_hNNqch50sLI,48945
54
54
  cucu/reporter/external/dataTables.bootstrap.min.css,sha256=AVjWb9eSGQ0-3f4WNiVU1pfkyoNvthJdaw_IxK9Y2c0,10611
@@ -59,15 +59,14 @@ cucu/reporter/external/popper.min.js,sha256=pS96pU17yq-gVu4KBQJi38VpSuKN7otMrDQp
59
59
  cucu/reporter/templates/feature.html,sha256=IBkwGiul-sRO5lT8q8VFXMUJx1owsAd1YbdDzziSjKw,3645
60
60
  cucu/reporter/templates/flat.html,sha256=JGsMq-IWz6YUpJX9hcN65-15HxcX3NJclOmMDtW3HZE,2358
61
61
  cucu/reporter/templates/index.html,sha256=LFth3SS__9881NKvPIIFdnrQEIcDTXWvToSWKNtjyKI,2726
62
- cucu/reporter/templates/layout.html,sha256=mtlJZEERJ_TJ4eHYhWpGORlcYQWjR7K5BUVpuHnRIqw,3773
62
+ cucu/reporter/templates/layout.html,sha256=2iDRbm8atO8mgHWgijIvDCrBMKvcP6YHrmr95WtJiE4,4561
63
63
  cucu/reporter/templates/scenario.html,sha256=Eomxn7_gxrOeWPXKQrnUt3pgKlWeC3PTiM04LMtDI44,10113
64
- cucu/steps/__init__.py,sha256=uKYQIa6zCC0TZM6lsGS8tdBpnwTloMH_YKoGXDuz0hM,753
64
+ cucu/steps/__init__.py,sha256=seSmASBlWu6-6wbFbvEbPwigBcRXiYP18C4X_2cW8Ng,753
65
65
  cucu/steps/base_steps.py,sha256=0fPvdaKoan8lMAKrDnK0-zrALpxm11P1zVAY5CN7iXA,1893
66
66
  cucu/steps/browser_steps.py,sha256=RJmQcvA7S5toiJSBCOzhwZwFP4YCA4cxO36HSk4wiHY,10381
67
67
  cucu/steps/button_steps.py,sha256=1C1UWVD4qs_3FuMlW13yg488C8u3rZYZVv384d_KgJE,2535
68
68
  cucu/steps/checkbox_steps.py,sha256=FQNm8M3y7rbXiHKBRUhHDGPBAvgQZ9QGOt3oDttA2qs,3094
69
69
  cucu/steps/command_steps.py,sha256=nVCc8-TEitetk-zhk4z1wa0owqLQyHeQVH5THioUw-k,5094
70
- cucu/steps/comment_steps.py,sha256=KcU0Ya8XSjYEh8gdUGh0qsAxgB_Ru977E84yJaXrvz0,379
71
70
  cucu/steps/draggable_steps.py,sha256=lnQLicp0GZJaxD_Qm2P13ruUZAsl3mptwaI5-SQ6XJ0,4655
72
71
  cucu/steps/dropdown_steps.py,sha256=abykG--m79kDQ4LU1tm73fNLFPmrKDavyFzJb2MYCu0,15601
73
72
  cucu/steps/file_input_steps.py,sha256=LLMAozVpceLMD-kJOE-auKHAdWLbNprH8eCfVQuNoGg,5523
@@ -79,6 +78,7 @@ cucu/steps/link_steps.py,sha256=MQLxyjCbiF2dOsmj6IrKKlRYhaqJjxDUNTf5Cau4J0w,1625
79
78
  cucu/steps/menuitem_steps.py,sha256=9JlaPO6BSmW2GPmk43gxGy5S03rEtEx4KE0uCFBkjk0,1133
80
79
  cucu/steps/platform_steps.py,sha256=G7HtBMhdRu58-2_LdXC5rkJM9F1ivGdlRa9BzTiHaaY,754
81
80
  cucu/steps/radio_steps.py,sha256=3NeEXK_Sd2J-qWM0_2togWKh52vxsJCbbH5G7fPo-Ng,5645
81
+ cucu/steps/section_steps.py,sha256=XeSvLkf7o_VIoVgwyxA36-9H_9XIUiAAJ6EbIqeshIE,645
82
82
  cucu/steps/step_utils.py,sha256=Chd0NQbMnfAEJmQkoVQRMbVRbCnJIBvVeH7CmXrCMm0,1417
83
83
  cucu/steps/tab_steps.py,sha256=TVVytkihvJ2GYQ9bwAs1CVzb-twzUq11QONlEbd6uO0,1818
84
84
  cucu/steps/table_steps.py,sha256=L497X4SnUlHG26Tp4FaLMke6HdqF2yIPj5lL6rBxIaw,13724
@@ -86,8 +86,8 @@ cucu/steps/tables.js,sha256=Os2a7Fo-cg03XVli7USvcnBVad4N7idXr-HBuzdLvVQ,945
86
86
  cucu/steps/text_steps.py,sha256=Jj_GHoHeemNwVdUOdqcehArNp7WM-WMjljA4w0pLXuw,2576
87
87
  cucu/steps/variable_steps.py,sha256=WSctH3_xcxjijGPYZlxp-foC_SIAAKtF__saNtgZJbk,2966
88
88
  cucu/steps/webserver_steps.py,sha256=wWkpSvcSMdiskPkh4cqlepWx1nkvEpTU2tRXQmPDbyo,1410
89
- cucu-1.1.2.dist-info/METADATA,sha256=dUcLBWY-bMgZQBL79R-zDUhUOGlfLQi1780LUll8a1c,16935
90
- cucu-1.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
91
- cucu-1.1.2.dist-info/entry_points.txt,sha256=YEXTyEfIZbcV0GJ9R3Gfu3j6DcOJJK7_XHkJqE3Yiao,39
92
- cucu-1.1.2.dist-info/licenses/LICENSE,sha256=WfgJYF9EaQoL_OeWr2Qd0MxhhFegDfzWSUmvDTwFxis,1721
93
- cucu-1.1.2.dist-info/RECORD,,
89
+ cucu-1.2.1.dist-info/METADATA,sha256=TdZuQu4Kz2AroxSSPxfqB9HKatZpOYm1XRC_OA2qVPs,16535
90
+ cucu-1.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
91
+ cucu-1.2.1.dist-info/entry_points.txt,sha256=YEXTyEfIZbcV0GJ9R3Gfu3j6DcOJJK7_XHkJqE3Yiao,39
92
+ cucu-1.2.1.dist-info/licenses/LICENSE,sha256=WfgJYF9EaQoL_OeWr2Qd0MxhhFegDfzWSUmvDTwFxis,1721
93
+ cucu-1.2.1.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- from behave import use_step_matcher
2
-
3
- from cucu import step
4
-
5
- use_step_matcher("re") # use regex to match comments
6
-
7
-
8
- @step("#.*")
9
- def comment_step(ctx):
10
- """
11
- A no-op step so that we can see "comments" in results and report.
12
- Usage: add `* #` to the line you want to show up.
13
- """
14
- pass
15
-
16
-
17
- use_step_matcher("parse") # set this back to cucu's default matcher parser
File without changes