codemie-test-harness 0.1.167__py3-none-any.whl → 0.1.168__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 codemie-test-harness might be problematic. Click here for more details.
- codemie_test_harness/tests/ui/pageobject/base_page.py +24 -24
- codemie_test_harness/tests/ui/pageobject/components/__init__.py +2 -2
- codemie_test_harness/tests/ui/pageobject/components/execution_history_row.py +3 -3
- codemie_test_harness/tests/ui/pageobject/components/{header.py → menu.py} +57 -111
- codemie_test_harness/tests/ui/pageobject/components/pop_up.py +2 -2
- codemie_test_harness/tests/ui/pageobject/components/workflow_card.py +7 -10
- codemie_test_harness/tests/ui/pageobject/components/workflow_execution_history_item.py +9 -9
- codemie_test_harness/tests/ui/pageobject/components/workflow_execution_state.py +1 -1
- codemie_test_harness/tests/ui/pageobject/components/workflow_sidebar.py +16 -16
- codemie_test_harness/tests/ui/pageobject/workflows/base_workflow_form_page.py +32 -65
- codemie_test_harness/tests/ui/pageobject/workflows/create_workflow_page.py +4 -4
- codemie_test_harness/tests/ui/pageobject/workflows/edit_workflow_page.py +6 -4
- codemie_test_harness/tests/ui/pageobject/workflows/workflow_details_page.py +32 -61
- codemie_test_harness/tests/ui/pageobject/workflows/workflow_executions_page.py +17 -23
- codemie_test_harness/tests/ui/pageobject/workflows/workflow_template_details.py +5 -11
- codemie_test_harness/tests/ui/pageobject/workflows/workflow_templates_page.py +5 -2
- codemie_test_harness/tests/ui/pageobject/workflows/workflows_page.py +3 -5
- codemie_test_harness/tests/ui/workflows/__init__.py +0 -0
- codemie_test_harness/tests/ui/{test_create_workflow.py → workflows/test_create_workflow.py} +12 -33
- codemie_test_harness/tests/ui/{test_edit_workflow.py → workflows/test_edit_workflow.py} +14 -34
- codemie_test_harness/tests/ui/{test_workflow_details.py → workflows/test_workflow_details.py} +11 -11
- codemie_test_harness/tests/ui/{test_workflow_executions_page.py → workflows/test_workflow_executions_page.py} +0 -2
- codemie_test_harness/tests/ui/{test_workflow_templates.py → workflows/test_workflow_templates.py} +0 -2
- codemie_test_harness/tests/ui/{test_workflows.py → workflows/test_workflows.py} +8 -6
- {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/METADATA +2 -2
- {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/RECORD +28 -27
- {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/WHEEL +0 -0
- {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/entry_points.txt +0 -0
|
@@ -4,7 +4,7 @@ from playwright.sync_api import expect
|
|
|
4
4
|
from reportportal_client import step
|
|
5
5
|
|
|
6
6
|
from codemie_test_harness.tests.ui.pageobject.components.pop_up import PopUp
|
|
7
|
-
from codemie_test_harness.tests.ui.pageobject.components.
|
|
7
|
+
from codemie_test_harness.tests.ui.pageobject.components.menu import Menu
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class BasePage:
|
|
@@ -16,7 +16,7 @@ class BasePage:
|
|
|
16
16
|
# Component properties using @property decorator
|
|
17
17
|
@property
|
|
18
18
|
def back_button(self):
|
|
19
|
-
"""Back button in the
|
|
19
|
+
"""Back button in the menu."""
|
|
20
20
|
return self.page.locator(
|
|
21
21
|
'//div[not(contains(@class,"justify-end"))]/button[contains(@class,"secondary medium")]'
|
|
22
22
|
).first
|
|
@@ -27,9 +27,9 @@ class BasePage:
|
|
|
27
27
|
return PopUp(self.page)
|
|
28
28
|
|
|
29
29
|
@property
|
|
30
|
-
def
|
|
31
|
-
"""
|
|
32
|
-
return
|
|
30
|
+
def menu(self):
|
|
31
|
+
"""Menu component instance."""
|
|
32
|
+
return Menu(self.page)
|
|
33
33
|
|
|
34
34
|
# Common page elements
|
|
35
35
|
@property
|
|
@@ -55,44 +55,44 @@ class BasePage:
|
|
|
55
55
|
# Navigation methods
|
|
56
56
|
@step
|
|
57
57
|
def go_to_workflows_page(self):
|
|
58
|
-
"""Navigate to workflows page using
|
|
59
|
-
self.
|
|
58
|
+
"""Navigate to workflows page using menu navigation."""
|
|
59
|
+
self.menu.navigate_to_workflows()
|
|
60
60
|
return self
|
|
61
61
|
|
|
62
62
|
@step
|
|
63
63
|
def go_to_assistants_page(self):
|
|
64
|
-
"""Navigate to assistants page using
|
|
65
|
-
self.
|
|
64
|
+
"""Navigate to assistants page using menu navigation."""
|
|
65
|
+
self.menu.navigate_to_assistants()
|
|
66
66
|
return self
|
|
67
67
|
|
|
68
68
|
@step
|
|
69
69
|
def go_to_chats_page(self):
|
|
70
|
-
"""Navigate to chats page using
|
|
71
|
-
self.
|
|
70
|
+
"""Navigate to chats page using menu navigation."""
|
|
71
|
+
self.menu.navigate_to_chats()
|
|
72
72
|
return self
|
|
73
73
|
|
|
74
74
|
@step
|
|
75
75
|
def go_to_applications_page(self):
|
|
76
|
-
"""Navigate to applications page using
|
|
77
|
-
self.
|
|
76
|
+
"""Navigate to applications page using menu navigation."""
|
|
77
|
+
self.menu.navigate_to_applications()
|
|
78
78
|
return self
|
|
79
79
|
|
|
80
80
|
@step
|
|
81
81
|
def go_to_integrations_page(self):
|
|
82
|
-
"""Navigate to integrations page using
|
|
83
|
-
self.
|
|
82
|
+
"""Navigate to integrations page using menu navigation."""
|
|
83
|
+
self.menu.navigate_to_integrations()
|
|
84
84
|
return self
|
|
85
85
|
|
|
86
86
|
@step
|
|
87
87
|
def go_to_data_sources_page(self):
|
|
88
|
-
"""Navigate to data sources page using
|
|
89
|
-
self.
|
|
88
|
+
"""Navigate to data sources page using menu navigation."""
|
|
89
|
+
self.menu.navigate_to_data_sources()
|
|
90
90
|
return self
|
|
91
91
|
|
|
92
92
|
@step
|
|
93
93
|
def go_to_help_page(self):
|
|
94
|
-
"""Navigate to help page using
|
|
95
|
-
self.
|
|
94
|
+
"""Navigate to help page using menu navigation."""
|
|
95
|
+
self.menu.navigate_to_help()
|
|
96
96
|
return self
|
|
97
97
|
|
|
98
98
|
# Pop-up interaction methods
|
|
@@ -164,10 +164,10 @@ class BasePage:
|
|
|
164
164
|
"""Verify that the new release popup is visible with expected content."""
|
|
165
165
|
expect(self.pop_up.cancel).to_have_text("Got It, Thanks!")
|
|
166
166
|
expect(self.pop_up.submit).to_have_text("Tell Me More")
|
|
167
|
-
expect(self.pop_up.
|
|
167
|
+
expect(self.pop_up.menu).to_have_text("New CodeMie Release")
|
|
168
168
|
expect(self.pop_up.body).to_have_text(
|
|
169
169
|
re.compile(
|
|
170
|
-
r"Great news! We've rolled out new CodeMie version
|
|
170
|
+
r"Great news! We've rolled out new CodeMie version 2.\d.\d+ to enhance your experience. Take a moment to "
|
|
171
171
|
"explore what's new and discover how these changes can benefit you! Please review Release Notes!"
|
|
172
172
|
)
|
|
173
173
|
)
|
|
@@ -182,9 +182,9 @@ class BasePage:
|
|
|
182
182
|
|
|
183
183
|
# Common verification methods
|
|
184
184
|
@step
|
|
185
|
-
def
|
|
186
|
-
"""Verify that the
|
|
187
|
-
self.
|
|
185
|
+
def should_have_menu_visible(self):
|
|
186
|
+
"""Verify that the menu is visible."""
|
|
187
|
+
self.menu.should_be_visible()
|
|
188
188
|
return self
|
|
189
189
|
|
|
190
190
|
@step
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .workflow_card import WorkflowCard
|
|
2
2
|
from .pop_up import PopUp
|
|
3
|
-
from .
|
|
3
|
+
from .menu import Menu
|
|
4
4
|
from .workflow_sidebar import WorkflowSidebar
|
|
5
5
|
from .execution_history_row import ExecutionHistoryRow
|
|
6
6
|
from .workflow_state_card import WorkflowStateCard
|
|
@@ -10,7 +10,7 @@ from .workflow_execution_state import WorkflowExecutionState
|
|
|
10
10
|
__all__ = [
|
|
11
11
|
"WorkflowCard",
|
|
12
12
|
"PopUp",
|
|
13
|
-
"
|
|
13
|
+
"Menu",
|
|
14
14
|
"WorkflowSidebar",
|
|
15
15
|
"ExecutionHistoryRow",
|
|
16
16
|
"WorkflowStateCard",
|
|
@@ -122,7 +122,7 @@ class ExecutionHistoryRow:
|
|
|
122
122
|
self.should_have_status("In Progress")
|
|
123
123
|
expect(self.status_badge).to_have_class("bg-in-progress-secondary")
|
|
124
124
|
expect(self.status_badge).to_have_class("text-in-progress-main")
|
|
125
|
-
expect(self.status_badge).to_have_class("border-in-progress-
|
|
125
|
+
expect(self.status_badge).to_have_class("border-in-progress-border")
|
|
126
126
|
expect(self.status_dot).to_have_class("animate-pulse")
|
|
127
127
|
|
|
128
128
|
@step
|
|
@@ -131,7 +131,7 @@ class ExecutionHistoryRow:
|
|
|
131
131
|
self.should_have_status("Succeeded")
|
|
132
132
|
expect(self.status_badge).to_contain_class("bg-success-secondary")
|
|
133
133
|
expect(self.status_badge).to_contain_class("text-success-main")
|
|
134
|
-
expect(self.status_badge).to_contain_class("border-success-
|
|
134
|
+
expect(self.status_badge).to_contain_class("border-success-border")
|
|
135
135
|
|
|
136
136
|
@step
|
|
137
137
|
def should_have_failed_status(self):
|
|
@@ -139,7 +139,7 @@ class ExecutionHistoryRow:
|
|
|
139
139
|
self.should_have_status("Failed")
|
|
140
140
|
expect(self.status_badge).to_contain_class("bg-error-secondary")
|
|
141
141
|
expect(self.status_badge).to_contain_class("text-error-main")
|
|
142
|
-
expect(self.status_badge).to_contain_class("border-error-
|
|
142
|
+
expect(self.status_badge).to_contain_class("border-error-border")
|
|
143
143
|
|
|
144
144
|
@step
|
|
145
145
|
def should_have_prompt(self, expected_prompt: str):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Menu component page object for the main navigation menu.
|
|
3
3
|
Contains methods for interacting with navigation links, logo, and user profile.
|
|
4
4
|
"""
|
|
5
5
|
|
|
@@ -7,23 +7,23 @@ from reportportal_client import step
|
|
|
7
7
|
from playwright.sync_api import expect
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class
|
|
11
|
-
"""
|
|
10
|
+
class Menu:
|
|
11
|
+
"""Menu component with property-based element locators."""
|
|
12
12
|
|
|
13
13
|
def __init__(self, page):
|
|
14
14
|
self.page = page
|
|
15
15
|
|
|
16
|
-
#
|
|
16
|
+
# Menu elements using @property decorator
|
|
17
17
|
@property
|
|
18
|
-
def
|
|
19
|
-
"""Main
|
|
18
|
+
def menu_container(self):
|
|
19
|
+
"""Main menu container."""
|
|
20
20
|
return self.page.locator("//body//header")
|
|
21
21
|
|
|
22
22
|
@property
|
|
23
23
|
def logo_link(self):
|
|
24
24
|
"""Logo link element."""
|
|
25
|
-
return self.
|
|
26
|
-
|
|
25
|
+
return self.menu_container.locator(
|
|
26
|
+
"a.h-12.flex.grow.gap-4.items-center.relative.select-none.text-nowrap.cursor-pointer.group"
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
@property
|
|
@@ -33,13 +33,13 @@ class Header:
|
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def logo_tooltip(self):
|
|
36
|
-
"""Logo tooltip text."""
|
|
37
|
-
return self.page.locator('
|
|
36
|
+
"""Logo tooltip text whn menu is expanded."""
|
|
37
|
+
return self.page.locator('a:has-text("EPAM AI/RUN"):has-text("CodeMie")')
|
|
38
38
|
|
|
39
39
|
@property
|
|
40
40
|
def top_nav(self):
|
|
41
41
|
"""Top navigation container."""
|
|
42
|
-
return self.
|
|
42
|
+
return self.menu_container.locator('nav[aria-label="top-nav-links"]')
|
|
43
43
|
|
|
44
44
|
@property
|
|
45
45
|
def chats_link(self):
|
|
@@ -64,7 +64,7 @@ class Header:
|
|
|
64
64
|
@property
|
|
65
65
|
def secondary_nav(self):
|
|
66
66
|
"""Secondary navigation container."""
|
|
67
|
-
return self.
|
|
67
|
+
return self.menu_container.locator('nav[aria-label="secondary-nav-links"]')
|
|
68
68
|
|
|
69
69
|
@property
|
|
70
70
|
def integrations_link(self):
|
|
@@ -79,73 +79,51 @@ class Header:
|
|
|
79
79
|
@property
|
|
80
80
|
def bottom_nav(self):
|
|
81
81
|
"""Bottom navigation container."""
|
|
82
|
-
return self.
|
|
82
|
+
return self.menu_container.locator('nav[aria-label="bottom-nav-links"]')
|
|
83
83
|
|
|
84
84
|
@property
|
|
85
|
-
def
|
|
86
|
-
"""
|
|
87
|
-
return self.bottom_nav.locator(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def user_profile_container(self):
|
|
91
|
-
"""User profile container."""
|
|
92
|
-
return self.header_container.locator("//span[text()='User Profile']/..")
|
|
93
|
-
|
|
94
|
-
@property
|
|
95
|
-
def user_profile_button(self):
|
|
96
|
-
"""User profile button."""
|
|
97
|
-
return self.user_profile_container.locator("button")
|
|
98
|
-
|
|
99
|
-
@property
|
|
100
|
-
def user_avatar(self):
|
|
101
|
-
"""User avatar image."""
|
|
102
|
-
return self.user_profile_button.locator('img[alt="User profile"]')
|
|
103
|
-
|
|
104
|
-
@property
|
|
105
|
-
def user_profile_tooltip(self):
|
|
106
|
-
"""User profile tooltip text."""
|
|
107
|
-
return self.page.locator('span:has-text("User Profile")')
|
|
108
|
-
|
|
109
|
-
# Navigation link tooltips
|
|
110
|
-
@property
|
|
111
|
-
def chats_tooltip(self):
|
|
112
|
-
"""Chats tooltip text."""
|
|
113
|
-
return self.page.locator('span:has-text("Chats")')
|
|
85
|
+
def faq_assistant_link(self):
|
|
86
|
+
"""FAQ assistant navigation link."""
|
|
87
|
+
return self.bottom_nav.locator(
|
|
88
|
+
'a[href="#/assistants/codemie-onboarding/start"]'
|
|
89
|
+
)
|
|
114
90
|
|
|
115
91
|
@property
|
|
116
|
-
def
|
|
117
|
-
"""
|
|
118
|
-
return self.
|
|
92
|
+
def prompt_assistant_link(self):
|
|
93
|
+
"""Prompt Engineer assistant navigation link."""
|
|
94
|
+
return self.bottom_nav.locator('a[href="#/assistants/prompt-engineer/start"]')
|
|
119
95
|
|
|
120
96
|
@property
|
|
121
|
-
def
|
|
122
|
-
"""
|
|
123
|
-
return self.
|
|
97
|
+
def switch_new_codemie(self):
|
|
98
|
+
"""Switch to new CodeMie."""
|
|
99
|
+
return self.menu_container.locator(".switch")
|
|
124
100
|
|
|
125
101
|
@property
|
|
126
|
-
def
|
|
127
|
-
"""
|
|
128
|
-
return self.
|
|
102
|
+
def hide_expand_menu_button(self):
|
|
103
|
+
"""Hide/Expand menu button."""
|
|
104
|
+
return self.menu_container.locator(
|
|
105
|
+
'button[type="button"].rounded-lg.flex.items-center'
|
|
106
|
+
)
|
|
129
107
|
|
|
130
108
|
@property
|
|
131
|
-
def
|
|
132
|
-
"""
|
|
133
|
-
return self.
|
|
109
|
+
def help_link(self):
|
|
110
|
+
"""Help navigation link."""
|
|
111
|
+
return self.bottom_nav.locator('a[href="#/help"]')
|
|
134
112
|
|
|
135
113
|
@property
|
|
136
|
-
def
|
|
137
|
-
"""
|
|
138
|
-
return self.
|
|
114
|
+
def user_profile_button(self):
|
|
115
|
+
"""User profile button."""
|
|
116
|
+
return self.menu_container.locator("button.cursor-pointer.group")
|
|
139
117
|
|
|
140
118
|
@property
|
|
141
|
-
def
|
|
142
|
-
"""
|
|
143
|
-
return self.
|
|
119
|
+
def user_avatar(self):
|
|
120
|
+
"""User avatar image."""
|
|
121
|
+
return self.user_profile_button.locator("img")
|
|
144
122
|
|
|
145
123
|
# Action methods
|
|
146
124
|
@step
|
|
147
125
|
def click_logo(self):
|
|
148
|
-
"""Click on the EPAM AI/Run logo to navigate to
|
|
126
|
+
"""Click on the EPAM AI/Run logo to navigate to new chat."""
|
|
149
127
|
self.logo_link.click()
|
|
150
128
|
return self
|
|
151
129
|
|
|
@@ -197,46 +175,6 @@ class Header:
|
|
|
197
175
|
self.user_profile_button.click()
|
|
198
176
|
return self
|
|
199
177
|
|
|
200
|
-
@step
|
|
201
|
-
def hover_over_navigation_item(self, navigation_item: str):
|
|
202
|
-
"""
|
|
203
|
-
Hover over a navigation item to display its tooltip.
|
|
204
|
-
|
|
205
|
-
Args:
|
|
206
|
-
navigation_item (str): The navigation item to hover over
|
|
207
|
-
('chats', 'assistants', 'workflows', 'applications',
|
|
208
|
-
'integrations', 'data_sources', 'help', 'logo', 'user_profile')
|
|
209
|
-
"""
|
|
210
|
-
navigation_items = {
|
|
211
|
-
"chats": self.chats_link,
|
|
212
|
-
"assistants": self.assistants_link,
|
|
213
|
-
"workflows": self.workflows_link,
|
|
214
|
-
"applications": self.applications_link,
|
|
215
|
-
"integrations": self.integrations_link,
|
|
216
|
-
"data_sources": self.data_sources_link,
|
|
217
|
-
"help": self.help_link,
|
|
218
|
-
"logo": self.logo_link,
|
|
219
|
-
"user_profile": self.user_profile_button,
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if navigation_item in navigation_items:
|
|
223
|
-
navigation_items[navigation_item].hover()
|
|
224
|
-
else:
|
|
225
|
-
raise ValueError(f"Unknown navigation item: {navigation_item}")
|
|
226
|
-
return self
|
|
227
|
-
|
|
228
|
-
@step
|
|
229
|
-
def wait_for_tooltip_to_appear(self, tooltip_text: str):
|
|
230
|
-
"""
|
|
231
|
-
Wait for a specific tooltip to appear.
|
|
232
|
-
|
|
233
|
-
Args:
|
|
234
|
-
tooltip_text (str): The text of the tooltip to wait for
|
|
235
|
-
"""
|
|
236
|
-
tooltip = self.page.locator(f'span:has-text("{tooltip_text}")')
|
|
237
|
-
tooltip.wait_for(state="visible")
|
|
238
|
-
return self
|
|
239
|
-
|
|
240
178
|
# Utility methods
|
|
241
179
|
@step
|
|
242
180
|
def get_active_navigation_item(self):
|
|
@@ -244,7 +182,7 @@ class Header:
|
|
|
244
182
|
Get the currently active navigation item.
|
|
245
183
|
Returns the href of the active navigation link.
|
|
246
184
|
"""
|
|
247
|
-
active_link = self.
|
|
185
|
+
active_link = self.menu_container.locator("a.bg-new-panel-secondary")
|
|
248
186
|
if active_link.is_visible():
|
|
249
187
|
return active_link.get_attribute("href")
|
|
250
188
|
return None
|
|
@@ -257,8 +195,8 @@ class Header:
|
|
|
257
195
|
# Verification methods
|
|
258
196
|
@step
|
|
259
197
|
def should_be_visible(self):
|
|
260
|
-
"""Verify that the
|
|
261
|
-
expect(self.
|
|
198
|
+
"""Verify that the menu is visible."""
|
|
199
|
+
expect(self.menu_container).to_be_visible()
|
|
262
200
|
return self
|
|
263
201
|
|
|
264
202
|
@step
|
|
@@ -293,12 +231,12 @@ class Header:
|
|
|
293
231
|
Verify that all main navigation elements are present and visible.
|
|
294
232
|
"""
|
|
295
233
|
navigation_structure = {
|
|
296
|
-
"
|
|
234
|
+
"menu": self.menu_container,
|
|
297
235
|
"logo": self.logo_link,
|
|
298
236
|
"top_nav": self.top_nav,
|
|
299
237
|
"secondary_nav": self.secondary_nav,
|
|
300
238
|
"bottom_nav": self.bottom_nav,
|
|
301
|
-
"user_profile": self.
|
|
239
|
+
"user_profile": self.user_profile_button,
|
|
302
240
|
"chats_link": self.chats_link,
|
|
303
241
|
"assistants_link": self.assistants_link,
|
|
304
242
|
"workflows_link": self.workflows_link,
|
|
@@ -306,6 +244,10 @@ class Header:
|
|
|
306
244
|
"integrations_link": self.integrations_link,
|
|
307
245
|
"data_sources_link": self.data_sources_link,
|
|
308
246
|
"help_link": self.help_link,
|
|
247
|
+
"faq_assistant_link": self.faq_assistant_link,
|
|
248
|
+
"prompt_assistant_link": self.prompt_assistant_link,
|
|
249
|
+
"switch_to_new_codemie": self.switch_new_codemie,
|
|
250
|
+
"hide_expand_menu": self.hide_expand_menu_button,
|
|
309
251
|
}
|
|
310
252
|
|
|
311
253
|
for element_name, element in navigation_structure.items():
|
|
@@ -322,9 +264,9 @@ class Header:
|
|
|
322
264
|
|
|
323
265
|
# Legacy methods for backward compatibility
|
|
324
266
|
@step
|
|
325
|
-
def
|
|
326
|
-
"""Check if the
|
|
327
|
-
return self.
|
|
267
|
+
def is_menu_visible(self):
|
|
268
|
+
"""Check if the menu is visible on the page."""
|
|
269
|
+
return self.menu_container.is_visible()
|
|
328
270
|
|
|
329
271
|
@step
|
|
330
272
|
def is_logo_visible(self):
|
|
@@ -359,12 +301,12 @@ class Header:
|
|
|
359
301
|
dict: A dictionary with the visibility status of each navigation section
|
|
360
302
|
"""
|
|
361
303
|
return {
|
|
362
|
-
"
|
|
304
|
+
"menu_visible": self.menu_container.is_visible(),
|
|
363
305
|
"logo_visible": self.logo_link.is_visible(),
|
|
364
306
|
"top_nav_visible": self.top_nav.is_visible(),
|
|
365
307
|
"secondary_nav_visible": self.secondary_nav.is_visible(),
|
|
366
308
|
"bottom_nav_visible": self.bottom_nav.is_visible(),
|
|
367
|
-
"user_profile_visible": self.
|
|
309
|
+
"user_profile_visible": self.user_profile_button.is_visible(),
|
|
368
310
|
"chats_link_visible": self.chats_link.is_visible(),
|
|
369
311
|
"assistants_link_visible": self.assistants_link.is_visible(),
|
|
370
312
|
"workflows_link_visible": self.workflows_link.is_visible(),
|
|
@@ -372,4 +314,8 @@ class Header:
|
|
|
372
314
|
"integrations_link_visible": self.integrations_link.is_visible(),
|
|
373
315
|
"data_sources_link_visible": self.data_sources_link.is_visible(),
|
|
374
316
|
"help_link_visible": self.help_link.is_visible(),
|
|
317
|
+
"faq_assistant_link_visible": self.faq_assistant_link.is_visible(),
|
|
318
|
+
"prompt_assistant_link_visible": self.prompt_assistant_link.is_visible(),
|
|
319
|
+
"switch_to_new_codemie_visible": self.switch_new_codemie.is_visible(),
|
|
320
|
+
"hide_expand_menu_visible": self.hide_expand_menu_button.is_visible(),
|
|
375
321
|
}
|
|
@@ -26,17 +26,17 @@ class WorkflowCard:
|
|
|
26
26
|
@property
|
|
27
27
|
def title(self):
|
|
28
28
|
"""Workflow title element."""
|
|
29
|
-
return self.card.locator(".
|
|
29
|
+
return self.card.locator(".whitespace-nowrap.truncate.font-semibold")
|
|
30
30
|
|
|
31
31
|
@property
|
|
32
32
|
def author(self):
|
|
33
33
|
"""Workflow author element."""
|
|
34
|
-
return self.card.locator(".text-
|
|
34
|
+
return self.card.locator(".text-xs.text-text-gray-300")
|
|
35
35
|
|
|
36
36
|
@property
|
|
37
37
|
def description(self):
|
|
38
38
|
"""Workflow description element."""
|
|
39
|
-
return self.card.locator("p.text-
|
|
39
|
+
return self.card.locator(".flex-row p.text-xs")
|
|
40
40
|
|
|
41
41
|
@property
|
|
42
42
|
def description_tooltip(self):
|
|
@@ -48,7 +48,7 @@ class WorkflowCard:
|
|
|
48
48
|
@property
|
|
49
49
|
def run_button(self):
|
|
50
50
|
"""Run workflow button."""
|
|
51
|
-
return self.card.locator("button.
|
|
51
|
+
return self.card.locator("button.gradient.medium")
|
|
52
52
|
|
|
53
53
|
@property
|
|
54
54
|
def menu_button(self):
|
|
@@ -137,20 +137,17 @@ class WorkflowCard:
|
|
|
137
137
|
@step
|
|
138
138
|
def should_have_title(self, expected_title: str):
|
|
139
139
|
"""Verify the workflow has the expected title."""
|
|
140
|
-
|
|
141
|
-
return self
|
|
140
|
+
return self.get_title() == expected_title
|
|
142
141
|
|
|
143
142
|
@step
|
|
144
143
|
def should_have_author(self, expected_author: str):
|
|
145
144
|
"""Verify the workflow has the expected author."""
|
|
146
|
-
|
|
147
|
-
return self
|
|
145
|
+
return self.get_author() == expected_author
|
|
148
146
|
|
|
149
147
|
@step
|
|
150
148
|
def should_have_description(self, expected_description: str):
|
|
151
149
|
"""Verify the workflow has the expected description."""
|
|
152
|
-
|
|
153
|
-
return self
|
|
150
|
+
return self.get_description() == expected_description
|
|
154
151
|
|
|
155
152
|
@step
|
|
156
153
|
def should_be_shared_with_project(self):
|
|
@@ -25,12 +25,12 @@ class WorkflowExecutionHistoryItem:
|
|
|
25
25
|
@property
|
|
26
26
|
def status_badge(self):
|
|
27
27
|
"""Status badge (Succeeded/Failed/Running)."""
|
|
28
|
-
return self.item.locator(".flex.flex-row.items-center.
|
|
28
|
+
return self.item.locator(".flex.flex-row.items-center.border")
|
|
29
29
|
|
|
30
30
|
@property
|
|
31
31
|
def status_dot(self):
|
|
32
32
|
"""Status indicator dot."""
|
|
33
|
-
return self.status_badge.locator(".rounded-full.
|
|
33
|
+
return self.status_badge.locator(".rounded-full.inline-block")
|
|
34
34
|
|
|
35
35
|
@property
|
|
36
36
|
def timestamp(self):
|
|
@@ -38,8 +38,8 @@ class WorkflowExecutionHistoryItem:
|
|
|
38
38
|
return self.item.locator(".text-text-tertiary.text-xs span")
|
|
39
39
|
|
|
40
40
|
@property
|
|
41
|
-
def
|
|
42
|
-
"""Execution
|
|
41
|
+
def execution_body(self):
|
|
42
|
+
"""Execution body text element."""
|
|
43
43
|
return self.item.locator(
|
|
44
44
|
".truncate.overflow-hidden.whitespace-nowrap.min-w-0.text-sm"
|
|
45
45
|
)
|
|
@@ -47,7 +47,7 @@ class WorkflowExecutionHistoryItem:
|
|
|
47
47
|
@property
|
|
48
48
|
def menu_button(self):
|
|
49
49
|
"""Three dots menu button."""
|
|
50
|
-
return self.item.locator(
|
|
50
|
+
return self.item.locator("button.tertiary.medium.m-1")
|
|
51
51
|
|
|
52
52
|
# Utility methods
|
|
53
53
|
@step
|
|
@@ -58,7 +58,7 @@ class WorkflowExecutionHistoryItem:
|
|
|
58
58
|
@step
|
|
59
59
|
def get_execution_id_text(self) -> str:
|
|
60
60
|
"""Get execution ID text."""
|
|
61
|
-
return self.
|
|
61
|
+
return self.execution_body.text_content().strip()
|
|
62
62
|
|
|
63
63
|
@step
|
|
64
64
|
def get_timestamp_text(self) -> str:
|
|
@@ -162,13 +162,13 @@ class WorkflowExecutionHistoryItem:
|
|
|
162
162
|
@step
|
|
163
163
|
def should_have_execution_id(self, expected_id: str):
|
|
164
164
|
"""Verify the execution ID."""
|
|
165
|
-
expect(self.
|
|
165
|
+
expect(self.execution_body).to_have_text(expected_id)
|
|
166
166
|
return self
|
|
167
167
|
|
|
168
168
|
@step
|
|
169
169
|
def should_have_execution_id_pattern(self, pattern: str):
|
|
170
170
|
"""Verify the execution ID matches a pattern (regex)."""
|
|
171
|
-
expect(self.
|
|
171
|
+
expect(self.execution_body).to_match(pattern)
|
|
172
172
|
return self
|
|
173
173
|
|
|
174
174
|
@step
|
|
@@ -213,7 +213,7 @@ class WorkflowExecutionHistoryItem:
|
|
|
213
213
|
"""Verify all main elements are visible."""
|
|
214
214
|
expect(self.container).to_be_visible()
|
|
215
215
|
expect(self.status_badge).to_be_visible()
|
|
216
|
-
expect(self.
|
|
216
|
+
expect(self.execution_body).to_be_visible()
|
|
217
217
|
expect(self.timestamp).to_be_visible()
|
|
218
218
|
expect(self.menu_button).to_be_visible()
|
|
219
219
|
return self
|
|
@@ -97,7 +97,7 @@ class WorkflowExecutionState:
|
|
|
97
97
|
@property
|
|
98
98
|
def expanded_content(self):
|
|
99
99
|
"""Expanded content container (when state is expanded)."""
|
|
100
|
-
return self.state.locator("div.
|
|
100
|
+
return self.state.locator("div.markdown")
|
|
101
101
|
|
|
102
102
|
@property
|
|
103
103
|
def expanded_message(self):
|