cucu 1.0.0__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.

Files changed (83) hide show
  1. cucu/__init__.py +38 -0
  2. cucu/ansi_parser.py +58 -0
  3. cucu/behave_tweaks.py +196 -0
  4. cucu/browser/__init__.py +0 -0
  5. cucu/browser/core.py +80 -0
  6. cucu/browser/frames.py +106 -0
  7. cucu/browser/selenium.py +323 -0
  8. cucu/browser/selenium_tweaks.py +27 -0
  9. cucu/cli/__init__.py +3 -0
  10. cucu/cli/core.py +788 -0
  11. cucu/cli/run.py +207 -0
  12. cucu/cli/steps.py +137 -0
  13. cucu/cli/thread_dumper.py +55 -0
  14. cucu/config.py +440 -0
  15. cucu/edgedriver_autoinstaller/README.md +1 -0
  16. cucu/edgedriver_autoinstaller/__init__.py +37 -0
  17. cucu/edgedriver_autoinstaller/utils.py +231 -0
  18. cucu/environment.py +283 -0
  19. cucu/external/jquery/jquery-3.5.1.min.js +2 -0
  20. cucu/formatter/__init__.py +0 -0
  21. cucu/formatter/cucu.py +261 -0
  22. cucu/formatter/json.py +321 -0
  23. cucu/formatter/junit.py +289 -0
  24. cucu/fuzzy/__init__.py +3 -0
  25. cucu/fuzzy/core.py +107 -0
  26. cucu/fuzzy/fuzzy.js +253 -0
  27. cucu/helpers.py +875 -0
  28. cucu/hooks.py +205 -0
  29. cucu/language_server/__init__.py +3 -0
  30. cucu/language_server/core.py +114 -0
  31. cucu/lint/__init__.py +0 -0
  32. cucu/lint/linter.py +397 -0
  33. cucu/lint/rules/format.yaml +125 -0
  34. cucu/logger.py +113 -0
  35. cucu/matcher/__init__.py +0 -0
  36. cucu/matcher/core.py +30 -0
  37. cucu/page_checks.py +63 -0
  38. cucu/reporter/__init__.py +3 -0
  39. cucu/reporter/external/bootstrap.min.css +7 -0
  40. cucu/reporter/external/bootstrap.min.js +7 -0
  41. cucu/reporter/external/dataTables.bootstrap.min.css +1 -0
  42. cucu/reporter/external/dataTables.bootstrap.min.js +14 -0
  43. cucu/reporter/external/jquery-3.5.1.min.js +2 -0
  44. cucu/reporter/external/jquery.dataTables.min.js +192 -0
  45. cucu/reporter/external/popper.min.js +5 -0
  46. cucu/reporter/favicon.png +0 -0
  47. cucu/reporter/html.py +452 -0
  48. cucu/reporter/templates/feature.html +72 -0
  49. cucu/reporter/templates/flat.html +48 -0
  50. cucu/reporter/templates/index.html +49 -0
  51. cucu/reporter/templates/layout.html +109 -0
  52. cucu/reporter/templates/scenario.html +200 -0
  53. cucu/steps/__init__.py +27 -0
  54. cucu/steps/base_steps.py +88 -0
  55. cucu/steps/browser_steps.py +337 -0
  56. cucu/steps/button_steps.py +91 -0
  57. cucu/steps/checkbox_steps.py +111 -0
  58. cucu/steps/command_steps.py +181 -0
  59. cucu/steps/comment_steps.py +17 -0
  60. cucu/steps/draggable_steps.py +168 -0
  61. cucu/steps/dropdown_steps.py +467 -0
  62. cucu/steps/file_input_steps.py +80 -0
  63. cucu/steps/filesystem_steps.py +144 -0
  64. cucu/steps/flow_control_steps.py +198 -0
  65. cucu/steps/image_steps.py +37 -0
  66. cucu/steps/input_steps.py +301 -0
  67. cucu/steps/link_steps.py +63 -0
  68. cucu/steps/menuitem_steps.py +39 -0
  69. cucu/steps/platform_steps.py +29 -0
  70. cucu/steps/radio_steps.py +187 -0
  71. cucu/steps/step_utils.py +55 -0
  72. cucu/steps/tab_steps.py +68 -0
  73. cucu/steps/table_steps.py +437 -0
  74. cucu/steps/tables.js +28 -0
  75. cucu/steps/text_steps.py +78 -0
  76. cucu/steps/variable_steps.py +100 -0
  77. cucu/steps/webserver_steps.py +40 -0
  78. cucu/utils.py +269 -0
  79. cucu-1.0.0.dist-info/METADATA +424 -0
  80. cucu-1.0.0.dist-info/RECORD +83 -0
  81. cucu-1.0.0.dist-info/WHEEL +4 -0
  82. cucu-1.0.0.dist-info/entry_points.txt +2 -0
  83. cucu-1.0.0.dist-info/licenses/LICENSE +32 -0
@@ -0,0 +1,187 @@
1
+ from cucu import fuzzy, helpers, retry, step
2
+ from cucu.config import CONFIG
3
+ from cucu.utils import take_saw_element_screenshot
4
+
5
+ from . import base_steps
6
+
7
+
8
+ def find_radio_button(ctx, name, index=0):
9
+ """
10
+ find a radio button on screen by fuzzy matching on the name provided and
11
+ the target element:
12
+
13
+ * <input type="radio">
14
+ * <* role="radio">
15
+
16
+ parameters:
17
+ ctx(object): behave context object used to share data between steps
18
+ name(str): name that identifies the desired radio button on screen
19
+ index(str): the index of the radio button if there are duplicates
20
+
21
+ returns:
22
+ the WebElement that matches the provided arguments.
23
+ """
24
+ ctx.check_browser_initialized()
25
+ element = fuzzy.find(
26
+ ctx.browser,
27
+ name,
28
+ [
29
+ 'input[type="radio"]',
30
+ '*[role="radio"]',
31
+ ],
32
+ index=index,
33
+ direction=fuzzy.Direction.RIGHT_TO_LEFT,
34
+ )
35
+
36
+ take_saw_element_screenshot(ctx, "radio button", name, index, element)
37
+
38
+ return element
39
+
40
+
41
+ def find_n_assert_radio_button(ctx, name, index=0, is_visible=True):
42
+ """
43
+ find and assert a radio button is visible
44
+
45
+ parameters:
46
+ ctx(object): behave context object used to share data between steps
47
+ name(str): name that identifies the desired radio button on screen
48
+ index(str): the index of the radio button if there are duplicates
49
+
50
+ returns:
51
+ the WebElement that matches the provided arguments.
52
+ """
53
+ radio = find_radio_button(ctx, name, index=index)
54
+
55
+ if is_visible:
56
+ if radio is None:
57
+ raise Exception(f'unable to find radio button "{name}"')
58
+ else:
59
+ if radio is not None:
60
+ raise Exception(f'able to find radio button "{name}"')
61
+
62
+ return radio
63
+
64
+
65
+ def find_n_select_radio_button(ctx, name, index=0, ignore_if_selected=False):
66
+ """
67
+ find and select a radio button
68
+
69
+ parameters:
70
+ ctx(object): behave context object used to share data between steps
71
+ name(str): name that identifies the desired radio button on screen
72
+ index(str): the index of the radio button if there are duplicates
73
+
74
+ returns:
75
+ the WebElement that matches the provided arguments.
76
+ """
77
+ ctx.check_browser_initialized()
78
+ radio = find_n_assert_radio_button(ctx, name, index=index)
79
+
80
+ if base_steps.is_disabled(radio):
81
+ raise RuntimeError(
82
+ "unable to select the radio button, as it is disabled"
83
+ )
84
+
85
+ selected = radio.get_attribute("checked") == "true"
86
+
87
+ if selected:
88
+ if ignore_if_selected:
89
+ return
90
+
91
+ raise Exception(f'radio button "{name}" already selected')
92
+
93
+ ctx.browser.click(radio)
94
+
95
+
96
+ def is_selected(radio):
97
+ """
98
+ internal method to check if radiobox is selected
99
+ """
100
+ return bool(radio.get_attribute("checked"))
101
+
102
+
103
+ def is_not_selected(radio):
104
+ """
105
+ internal method to check if a radiobox is not selected
106
+ """
107
+ return not is_selected(radio)
108
+
109
+
110
+ def select_radio_button(ctx, radiobox):
111
+ """
112
+ internal method to select a radio button that isn't already selected
113
+ """
114
+ ctx.check_browser_initialized()
115
+
116
+ if base_steps.is_disabled(radiobox):
117
+ raise RuntimeError(
118
+ "unable to select the radio button, as it is disabled"
119
+ )
120
+
121
+ selected = bool(radiobox.get_attribute("checked"))
122
+
123
+ if selected:
124
+ raise Exception("radiobox already selected")
125
+
126
+ ctx.browser.click(radiobox)
127
+
128
+
129
+ helpers.define_should_see_thing_with_name_steps(
130
+ "radio button", find_radio_button
131
+ )
132
+ helpers.define_action_on_thing_with_name_steps(
133
+ "radio button", "select", find_radio_button, select_radio_button
134
+ )
135
+ helpers.define_thing_with_name_in_state_steps(
136
+ "radio button", "selected", find_radio_button, is_selected, with_nth=True
137
+ )
138
+ helpers.define_thing_with_name_in_state_steps(
139
+ "radio button", "not selected", find_radio_button, is_not_selected
140
+ )
141
+ helpers.define_thing_with_name_in_state_steps(
142
+ "radio button", "disabled", find_radio_button, base_steps.is_disabled
143
+ )
144
+ helpers.define_thing_with_name_in_state_steps(
145
+ "radio button",
146
+ "not disabled",
147
+ find_radio_button,
148
+ base_steps.is_not_disabled,
149
+ )
150
+ helpers.define_run_steps_if_I_can_see_element_with_name_steps(
151
+ "radio", find_radio_button
152
+ )
153
+
154
+
155
+ @step('I immediately select the radio button "{name}" if it is not selected')
156
+ def immediately_select_the_radio_button_if_not_selected(ctx, name):
157
+ find_n_select_radio_button(ctx, name, ignore_if_selected=True)
158
+
159
+
160
+ @step('I select the radio button "{name}" if it is not selected')
161
+ def select_the_radio_button_if_not_selected(ctx, name):
162
+ retry(
163
+ find_n_select_radio_button,
164
+ retry_after_s=float(CONFIG["CUCU_SHORT_UI_RETRY_AFTER_S"]),
165
+ wait_up_to_s=float(CONFIG["CUCU_SHORT_UI_WAIT_TIMEOUT_S"]),
166
+ )(ctx, name, ignore_if_selected=True)
167
+
168
+
169
+ @step('I wait to select the radio button "{name}" if it is not selected')
170
+ def wait_to_select_the_radio_button_if_not_selected(ctx, name):
171
+ retry(find_n_select_radio_button)(ctx, name, ignore_if_selected=True)
172
+
173
+
174
+ @step(
175
+ 'I immediately select the "{nth:nth}" radio button "{name}" if it is not selected'
176
+ )
177
+ def immediately_select_nth_radio_button_if_not_selected(ctx, nth, name):
178
+ find_n_select_radio_button(ctx, name, nth, ignore_if_selected=True)
179
+
180
+
181
+ @step('I select the "{nth:nth}" radio button "{name}" if it is not selected')
182
+ def select_nth_radio_button(ctx, nth, name):
183
+ retry(
184
+ find_n_select_radio_button,
185
+ retry_after_s=float(CONFIG["CUCU_SHORT_UI_RETRY_AFTER_S"]),
186
+ wait_up_to_s=float(CONFIG["CUCU_SHORT_UI_WAIT_TIMEOUT_S"]),
187
+ )(ctx, name, nth, ignore_if_selected=True)
@@ -0,0 +1,55 @@
1
+ import re
2
+
3
+ from cucu import config
4
+
5
+
6
+ def search(regex, value):
7
+ """
8
+ search for a matching regex within the value provided.
9
+ """
10
+ match = re.search(regex, value)
11
+
12
+ if match is None:
13
+ raise RuntimeError(f'"{regex}" did not match anything in "{value}"')
14
+
15
+
16
+ def search_and_save(regex, value, name, variable):
17
+ """
18
+ search for a matching regex within the value provided and then save the value
19
+ of the group name provided to the variable name provided.
20
+ """
21
+ match = re.search(regex, value)
22
+
23
+ if match is None:
24
+ raise RuntimeError(f'"{regex}" did not match anything in "{value}"')
25
+
26
+ groups = match.groupdict()
27
+
28
+ if name in groups:
29
+ config.CONFIG[variable] = groups[name]
30
+
31
+ else:
32
+ raise RuntimeError(
33
+ f'group "{name}" not found when searching for regex "{regex}" in "{value}"'
34
+ )
35
+
36
+
37
+ def match_and_save(regex, value, name, variable):
38
+ """
39
+ match the regex in the value provided and then save the value of the group
40
+ name provided to the variable name provided.
41
+ """
42
+ match = re.match(regex, value)
43
+
44
+ if match is None:
45
+ raise RuntimeError(f'"{regex}" did not match "{value}"')
46
+
47
+ groups = match.groupdict()
48
+
49
+ if name in groups:
50
+ config.CONFIG[variable] = groups[name]
51
+
52
+ else:
53
+ raise RuntimeError(
54
+ f'group "{name}" not found when matching regex "{regex}" to "{value}"'
55
+ )
@@ -0,0 +1,68 @@
1
+ from cucu import fuzzy, helpers
2
+ from cucu.utils import take_saw_element_screenshot
3
+
4
+ from . import base_steps
5
+
6
+
7
+ def find_tab(ctx, name, index=0):
8
+ """
9
+ find a tab containing the text provide.
10
+
11
+ parameters:
12
+ ctx(object): behave context object used to share data between steps
13
+ name(str): name that identifies the desired tab on screen
14
+ index(str): the index of the tab if there are duplicates
15
+
16
+ returns:
17
+ the WebElement that matches the provided arguments.
18
+ """
19
+ ctx.check_browser_initialized()
20
+ element = fuzzy.find(ctx.browser, name, ['*[role="tab"]'], index=index)
21
+
22
+ take_saw_element_screenshot(ctx, "tab", name, index, element)
23
+
24
+ return element
25
+
26
+
27
+ def click_tab(ctx, tab):
28
+ """
29
+ internal method to click a tab
30
+ """
31
+ ctx.check_browser_initialized()
32
+
33
+ if base_steps.is_disabled(tab):
34
+ raise RuntimeError("unable to click the tab, as it is disabled")
35
+
36
+ ctx.browser.click(tab)
37
+
38
+
39
+ def is_selected(tab):
40
+ """
41
+ internal method to check if a tab is currently selected
42
+ """
43
+ return tab.get_attribute("aria-selected") == "true"
44
+
45
+
46
+ def is_not_selected(tab):
47
+ """
48
+ internal method to check if a tab is currently not selected
49
+ """
50
+ return not is_selected(tab)
51
+
52
+
53
+ helpers.define_should_see_thing_with_name_steps("tab", find_tab)
54
+ helpers.define_action_on_thing_with_name_steps(
55
+ "tab", "click", find_tab, click_tab
56
+ )
57
+ helpers.define_thing_with_name_in_state_steps(
58
+ "tab", "selected", find_tab, is_selected
59
+ )
60
+ helpers.define_thing_with_name_in_state_steps(
61
+ "tab", "not selected", find_tab, is_not_selected
62
+ )
63
+ helpers.define_thing_with_name_in_state_steps(
64
+ "tab", "disabled", find_tab, base_steps.is_disabled
65
+ )
66
+ helpers.define_thing_with_name_in_state_steps(
67
+ "tab", "not disabled", find_tab, base_steps.is_not_disabled
68
+ )