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.

Files changed (28) hide show
  1. codemie_test_harness/tests/ui/pageobject/base_page.py +24 -24
  2. codemie_test_harness/tests/ui/pageobject/components/__init__.py +2 -2
  3. codemie_test_harness/tests/ui/pageobject/components/execution_history_row.py +3 -3
  4. codemie_test_harness/tests/ui/pageobject/components/{header.py → menu.py} +57 -111
  5. codemie_test_harness/tests/ui/pageobject/components/pop_up.py +2 -2
  6. codemie_test_harness/tests/ui/pageobject/components/workflow_card.py +7 -10
  7. codemie_test_harness/tests/ui/pageobject/components/workflow_execution_history_item.py +9 -9
  8. codemie_test_harness/tests/ui/pageobject/components/workflow_execution_state.py +1 -1
  9. codemie_test_harness/tests/ui/pageobject/components/workflow_sidebar.py +16 -16
  10. codemie_test_harness/tests/ui/pageobject/workflows/base_workflow_form_page.py +32 -65
  11. codemie_test_harness/tests/ui/pageobject/workflows/create_workflow_page.py +4 -4
  12. codemie_test_harness/tests/ui/pageobject/workflows/edit_workflow_page.py +6 -4
  13. codemie_test_harness/tests/ui/pageobject/workflows/workflow_details_page.py +32 -61
  14. codemie_test_harness/tests/ui/pageobject/workflows/workflow_executions_page.py +17 -23
  15. codemie_test_harness/tests/ui/pageobject/workflows/workflow_template_details.py +5 -11
  16. codemie_test_harness/tests/ui/pageobject/workflows/workflow_templates_page.py +5 -2
  17. codemie_test_harness/tests/ui/pageobject/workflows/workflows_page.py +3 -5
  18. codemie_test_harness/tests/ui/workflows/__init__.py +0 -0
  19. codemie_test_harness/tests/ui/{test_create_workflow.py → workflows/test_create_workflow.py} +12 -33
  20. codemie_test_harness/tests/ui/{test_edit_workflow.py → workflows/test_edit_workflow.py} +14 -34
  21. codemie_test_harness/tests/ui/{test_workflow_details.py → workflows/test_workflow_details.py} +11 -11
  22. codemie_test_harness/tests/ui/{test_workflow_executions_page.py → workflows/test_workflow_executions_page.py} +0 -2
  23. codemie_test_harness/tests/ui/{test_workflow_templates.py → workflows/test_workflow_templates.py} +0 -2
  24. codemie_test_harness/tests/ui/{test_workflows.py → workflows/test_workflows.py} +8 -6
  25. {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/METADATA +2 -2
  26. {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/RECORD +28 -27
  27. {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/WHEEL +0 -0
  28. {codemie_test_harness-0.1.167.dist-info → codemie_test_harness-0.1.168.dist-info}/entry_points.txt +0 -0
@@ -14,7 +14,7 @@ class WorkflowSidebar:
14
14
  """
15
15
  self.page = page
16
16
 
17
- # Main container and header
17
+ # Main container and sidebar
18
18
  @property
19
19
  def sidebar_container(self):
20
20
  """Main sidebar container."""
@@ -57,8 +57,8 @@ class WorkflowSidebar:
57
57
 
58
58
  # Filters section
59
59
  @property
60
- def filters_header(self):
61
- """Filters section header."""
60
+ def filters_sidebar(self):
61
+ """Filters section sidebar."""
62
62
  return self.sidebar_container.locator('span:has-text("Filters")')
63
63
 
64
64
  @property
@@ -73,8 +73,8 @@ class WorkflowSidebar:
73
73
 
74
74
  # Project filter section
75
75
  @property
76
- def project_filter_header(self):
77
- """Project filter expandable header."""
76
+ def project_filter_sidebar(self):
77
+ """Project filter expandable sidebar."""
78
78
  return self.sidebar_container.locator('a:has-text("project")')
79
79
 
80
80
  @property
@@ -110,8 +110,8 @@ class WorkflowSidebar:
110
110
 
111
111
  # Shared filter section
112
112
  @property
113
- def shared_filter_header(self):
114
- """Shared filter expandable header."""
113
+ def shared_filter_sidebar(self):
114
+ """Shared filter expandable sidebar."""
115
115
  return self.sidebar_container.locator('a:has-text("shared")')
116
116
 
117
117
  @property
@@ -187,14 +187,14 @@ class WorkflowSidebar:
187
187
  def expand_project_filter(self):
188
188
  """Expand the project filter section."""
189
189
  if not self.is_project_filter_expanded():
190
- self.project_filter_header.click()
190
+ self.project_filter_sidebar.click()
191
191
  return self
192
192
 
193
193
  @step
194
194
  def collapse_project_filter(self):
195
195
  """Collapse the project filter section."""
196
196
  if self.is_project_filter_expanded():
197
- self.project_filter_header.click()
197
+ self.project_filter_sidebar.click()
198
198
  return self
199
199
 
200
200
  @step
@@ -222,14 +222,14 @@ class WorkflowSidebar:
222
222
  def expand_shared_filter(self):
223
223
  """Expand the shared filter section."""
224
224
  if not self.is_shared_filter_expanded():
225
- self.shared_filter_header.click()
225
+ self.shared_filter_sidebar.click()
226
226
  return self
227
227
 
228
228
  @step
229
229
  def collapse_shared_filter(self):
230
230
  """Collapse the shared filter section."""
231
231
  if self.is_shared_filter_expanded():
232
- self.shared_filter_header.click()
232
+ self.shared_filter_sidebar.click()
233
233
  return self
234
234
 
235
235
  @step
@@ -342,27 +342,27 @@ class WorkflowSidebar:
342
342
  @step
343
343
  def should_have_filters_section(self):
344
344
  """Verify that the filters section is visible."""
345
- expect(self.filters_header).to_be_visible()
345
+ expect(self.filters_sidebar).to_be_visible()
346
346
  return self
347
347
 
348
348
  @step
349
349
  def should_have_project_filter_collapsed(self):
350
350
  """Verify that the project filter is collapsed."""
351
- expect(self.project_filter_header).to_be_visible()
351
+ expect(self.project_filter_sidebar).to_be_visible()
352
352
  expect(self.project_multiselect).not_to_be_visible()
353
353
  return self
354
354
 
355
355
  @step
356
356
  def should_have_project_filter_expanded(self):
357
357
  """Verify that the project filter is expanded."""
358
- expect(self.project_filter_header).to_be_visible()
358
+ expect(self.project_filter_sidebar).to_be_visible()
359
359
  expect(self.project_multiselect).to_be_visible()
360
360
  return self
361
361
 
362
362
  @step
363
363
  def should_have_shared_filter_collapsed(self):
364
364
  """Verify that the shared filter is collapsed."""
365
- expect(self.shared_filter_header).to_be_visible()
365
+ expect(self.shared_filter_sidebar).to_be_visible()
366
366
  expect(self.with_project_radio_group).not_to_be_visible()
367
367
  expect(self.not_shared_radio_group).not_to_be_visible()
368
368
  return self
@@ -370,7 +370,7 @@ class WorkflowSidebar:
370
370
  @step
371
371
  def should_have_shared_filter_expanded(self):
372
372
  """Verify that the shared filter is expanded."""
373
- expect(self.shared_filter_header).to_be_visible()
373
+ expect(self.shared_filter_sidebar).to_be_visible()
374
374
  expect(self.with_project_radio_group).to_be_visible()
375
375
  expect(self.not_shared_radio_group).to_be_visible()
376
376
  return self
@@ -1,10 +1,10 @@
1
1
  import platform
2
2
  from playwright.sync_api import Page, Locator, expect
3
3
  from reportportal_client import step
4
- from typing import Optional
5
4
 
6
5
  from codemie_test_harness.tests.ui.pageobject.base_page import BasePage
7
6
  from codemie_test_harness.tests.ui.pageobject.components import WorkflowSidebar
7
+ from codemie_test_harness.tests.ui.pageobject.components import Menu
8
8
 
9
9
 
10
10
  class BaseWorkflowFormPage(BasePage):
@@ -13,6 +13,7 @@ class BaseWorkflowFormPage(BasePage):
13
13
  def __init__(self, page: Page):
14
14
  super().__init__(page)
15
15
  self.sidebar = WorkflowSidebar(page)
16
+ self._menu = Menu(page)
16
17
 
17
18
  # ==============================================
18
19
  # PROPERTIES - UI ELEMENTS
@@ -60,56 +61,58 @@ class BaseWorkflowFormPage(BasePage):
60
61
  @property
61
62
  def shared_switch(self) -> Locator:
62
63
  """Shared with Project Team switch."""
63
- return self.page.locator("//input[@id='shared']")
64
+ return self.page.locator("input#shared")
64
65
 
65
66
  @property
66
67
  def shared_switch_label(self) -> Locator:
67
68
  """Shared with Project Team switch label."""
68
- return self.page.locator("//label[@id='shared']")
69
+ return self.page.locator("label#shared")
69
70
 
70
71
  # ------ Name Field Elements ------
71
72
  @property
72
73
  def name_input(self) -> Locator:
73
74
  """Name input field."""
74
- return self.page.locator("#name")
75
+ return self.page.locator("input#name")
75
76
 
76
77
  @property
77
78
  def name_field_label(self) -> Locator:
78
79
  """Name field label."""
79
- return self.page.locator('div.text-sm.font-semibold:has-text("Name")')
80
+ return self.page.locator('.input-label:has-text("Name")')
80
81
 
81
82
  @property
82
83
  def name_error_message(self):
83
84
  """Name field error message."""
84
- return self.page.locator(".input-field-wrapper:has(#name) .input-error-message")
85
+ return self.page.locator(
86
+ "label.input-field-wrapper[for='name'] .input-error-message"
87
+ )
85
88
 
86
89
  # ------ Description Field Elements ------
87
90
  @property
88
91
  def description_textarea(self) -> Locator:
89
92
  """Description textarea field."""
90
- return self.page.locator("#description")
93
+ return self.page.locator("textarea#description")
91
94
 
92
95
  @property
93
96
  def description_field_label(self) -> Locator:
94
97
  """Description field label."""
95
- return self.page.locator('div.text-sm.font-semibold:has-text("Description")')
98
+ return self.page.locator('label[for="description"].textarea-label')
96
99
 
97
100
  # ------ Icon URL Field Elements ------
98
101
  @property
99
102
  def icon_url_input(self) -> Locator:
100
103
  """Icon URL input field."""
101
- return self.page.locator("#icon_url")
104
+ return self.page.locator("input#icon_url")
102
105
 
103
106
  @property
104
107
  def icon_url_field_label(self) -> Locator:
105
108
  """Icon URL field label."""
106
- return self.page.locator('div.text-sm.font-semibold:has-text("Icon URL")')
109
+ return self.page.locator('.input-label:has-text("Icon URL")')
107
110
 
108
111
  @property
109
112
  def icon_url_error_message(self):
110
113
  """Icon URL field error message."""
111
114
  return self.page.locator(
112
- ".input-field-wrapper:has(#icon_url) .input-error-message"
115
+ "label.input-field-wrapper[for='icon_url'] .input-error-message"
113
116
  )
114
117
 
115
118
  # ------ Workflow Mode Elements ------
@@ -118,11 +121,6 @@ class BaseWorkflowFormPage(BasePage):
118
121
  """Workflow Mode dropdown."""
119
122
  return self.page.locator('.p-dropdown[data-pc-name="dropdown"]')
120
123
 
121
- @property
122
- def workflow_mode_label(self) -> Locator:
123
- """Workflow Mode field label."""
124
- return self.page.locator('div.text-sm.font-semibold:has-text("Workflow Mode")')
125
-
126
124
  @property
127
125
  def workflow_mode_selected_value(self) -> Locator:
128
126
  """Currently selected workflow mode value."""
@@ -131,12 +129,12 @@ class BaseWorkflowFormPage(BasePage):
131
129
  @property
132
130
  def workflow_mode_info_icon(self) -> Locator:
133
131
  """Information icon next to workflow mode."""
134
- return self.page.locator(".scale-105.opacity-75 svg")
132
+ return self.page.locator(".flex.w-full.px-2.gap-2 .opacity-75 svg")
135
133
 
136
134
  @property
137
135
  def workflow_mode_description(self) -> Locator:
138
136
  """Workflow mode description text."""
139
- return self.page.locator(".flex.w-full.px-2.gap-2 .text-text-secondary.text-sm")
137
+ return self.page.locator(".flex.w-full.px-2.gap-2 .text-text-secondary.text-xs")
140
138
 
141
139
  # ------ YAML Configuration Elements ------
142
140
  @property
@@ -175,49 +173,48 @@ class BaseWorkflowFormPage(BasePage):
175
173
  @property
176
174
  def visualize_button(self) -> Locator:
177
175
  """Visualize button."""
178
- return self.page.locator('button.button.secondary.large:has-text("Visualize")')
176
+ return self.page.locator('button.button.secondary.medium:has-text("Visualize")')
179
177
 
180
178
  @property
181
179
  def visualization_placeholder(self) -> Locator:
182
180
  """Workflow visualization placeholder area."""
183
181
  return self.page.locator(
184
- "//div[text()=' Workflow visualisation ']/../following-sibling::div"
182
+ ".flex.flex-col.items-center.justify-center.bg-new-panel"
185
183
  )
186
184
 
187
185
  @property
188
186
  def visualization_placeholder_text(self) -> Locator:
189
187
  """Visualization placeholder text."""
190
- return self.page.locator(
191
- "//div[text()=' Workflow visualisation ']/../following-sibling::div/div[text()=' Workflow visualisation']"
192
- )
188
+ return self.visualization_placeholder.locator(":scope > .text-md")
193
189
 
194
190
  @property
195
191
  def workflow_diagram(self) -> Locator:
196
- """Workflow diagram image."""
197
- return self.page.locator(
198
- "//div[text()=' Workflow visualisation ']/../following-sibling::div//img[@alt='Workflow Diagram']"
199
- )
192
+ """Workflow diagram image (if/when present)."""
193
+ return self.visualization_placeholder.locator("img[alt='Workflow Diagram']")
200
194
 
201
195
  @property
202
196
  def reset_zooming(self) -> Locator:
203
197
  """Reset zooming button in visualization."""
204
- return self.page.locator(
205
- "//div[text()=' Workflow visualisation ']/../following-sibling::div/div/div/ul/li[2]"
198
+ return self.visualization_placeholder.locator(
199
+ "div.controll__buttons li.controll__home"
200
+ )
201
+
202
+ @property
203
+ def zoom_buttons(self) -> Locator:
204
+ """Zoom buttons."""
205
+ return self.visualization_placeholder.locator(
206
+ "div.controll__buttons li.controll__zoom-in"
206
207
  )
207
208
 
208
209
  @property
209
210
  def zoom_in_button(self) -> Locator:
210
211
  """Zoom in button in visualization."""
211
- return self.page.locator(
212
- "//div[text()=' Workflow visualisation ']/../following-sibling::div/div/div/ul/li[3]"
213
- )
212
+ return self.zoom_buttons.nth(0)
214
213
 
215
214
  @property
216
215
  def zoom_out_button(self) -> Locator:
217
216
  """Zoom out button in visualization."""
218
- return self.page.locator(
219
- "//div[text()=' Workflow visualisation ']/../following-sibling::div/div/div/ul/li[4]"
220
- )
217
+ return self.zoom_buttons.nth(1)
221
218
 
222
219
  # ==============================================
223
220
  # METHODS - ACTIONS & INTERACTIONS
@@ -275,14 +272,6 @@ class BaseWorkflowFormPage(BasePage):
275
272
  """Fill the icon URL field."""
276
273
  self.icon_url_input.fill(icon_url)
277
274
 
278
- # ------ Workflow Mode Actions ------
279
- @step
280
- def select_workflow_mode(self, mode: Optional[str] = None):
281
- """Select workflow mode from dropdown. If mode is None, just click to open."""
282
- self.workflow_mode_dropdown.click()
283
- if mode:
284
- self.page.locator(f'li:has-text("{mode}")').click()
285
-
286
275
  # ------ YAML Configuration Actions ------
287
276
  @step
288
277
  def fill_yaml_config(self, yaml_content: str):
@@ -366,27 +355,6 @@ class BaseWorkflowFormPage(BasePage):
366
355
  """Verify that the icon URL field is empty."""
367
356
  expect(self.icon_url_input).to_have_value("")
368
357
 
369
- # ------ Workflow Mode Verifications ------
370
- @step
371
- def should_have_workflow_mode_dropdown_visible(self):
372
- """Verify that the workflow mode dropdown is visible."""
373
- expect(self.workflow_mode_dropdown).to_be_visible()
374
-
375
- @step
376
- def should_have_workflow_mode_selected(self, mode: str):
377
- """Verify that the specified workflow mode is selected."""
378
- expect(self.workflow_mode_selected_value).to_have_text(mode)
379
-
380
- @step
381
- def should_show_workflow_mode_info(self):
382
- """Verify that workflow mode information is displayed."""
383
- expect(self.workflow_mode_info_icon).to_be_visible()
384
- expect(self.workflow_mode_description).to_be_visible()
385
- expect(self.workflow_mode_description).to_contain_text(
386
- "Sequential Mode offers full control. You define the workflow, choosing assistants and setting each step. "
387
- "It's perfect for tasks needing specific, orderly execution. Opt for this when detail and sequence matter."
388
- )
389
-
390
358
  # ------ YAML Configuration Verifications ------
391
359
  @step
392
360
  def should_have_yaml_editor_visible(self):
@@ -445,7 +413,6 @@ class BaseWorkflowFormPage(BasePage):
445
413
  expect(self.name_field_label).to_be_visible()
446
414
  expect(self.description_field_label).to_be_visible()
447
415
  expect(self.icon_url_field_label).to_be_visible()
448
- expect(self.workflow_mode_label).to_be_visible()
449
416
  expect(self.yaml_config_header).to_be_visible()
450
417
  expect(self.visualization_header).to_be_visible()
451
418
  return self
@@ -16,7 +16,7 @@ class CreateWorkflowPage(BaseWorkflowFormPage):
16
16
  super().__init__(page)
17
17
 
18
18
  # ==================== PROPERTIES ====================
19
- # Header elements specific to Create page
19
+ # Menu elements specific to Create page
20
20
  @property
21
21
  def page_title(self):
22
22
  """Page title 'Create Workflow'."""
@@ -24,7 +24,7 @@ class CreateWorkflowPage(BaseWorkflowFormPage):
24
24
 
25
25
  @property
26
26
  def create_button(self):
27
- """Create button in the header."""
27
+ """Create button in the menu."""
28
28
  return self.page.locator('button.button.primary.medium:has-text("Create")')
29
29
 
30
30
  # ==================== NAVIGATION METHODS ====================
@@ -91,8 +91,8 @@ class CreateWorkflowPage(BaseWorkflowFormPage):
91
91
  return self
92
92
 
93
93
  @step
94
- def should_have_header_elements_visible(self):
95
- """Verify that all header elements are visible."""
94
+ def should_have_menu_elements_visible(self):
95
+ """Verify that all menu elements are visible."""
96
96
  expect(self.back_button).to_be_visible()
97
97
  expect(self.page_title).to_be_visible()
98
98
  expect(self.cancel_button).to_be_visible()
@@ -27,7 +27,7 @@ class EditWorkflowPage(BaseWorkflowFormPage):
27
27
 
28
28
  @property
29
29
  def update_button(self) -> Locator:
30
- """Update button in the header."""
30
+ """Update button in the menu."""
31
31
  return self.page.locator('button.button.primary.medium:has-text("Update")')
32
32
 
33
33
  @property
@@ -68,7 +68,9 @@ class EditWorkflowPage(BaseWorkflowFormPage):
68
68
  @property
69
69
  def restore_button(self) -> Locator:
70
70
  """Restore button in history tab."""
71
- return self.page.locator('button.button.secondary.large:has-text("Restore")')
71
+ return self.page.locator(
72
+ 'button.primary.medium.self-center:has-text("Restore")'
73
+ )
72
74
 
73
75
  @property
74
76
  def history_yaml_editor(self) -> Locator:
@@ -230,8 +232,8 @@ class EditWorkflowPage(BaseWorkflowFormPage):
230
232
  expect(self.back_button).to_be_visible()
231
233
 
232
234
  @step
233
- def should_have_header_elements_visible(self):
234
- """Verify that all header elements are visible."""
235
+ def should_have_menu_elements_visible(self):
236
+ """Verify that all menu elements are visible."""
235
237
  expect(self.back_button).to_be_visible()
236
238
  expect(self.page_title).to_be_visible()
237
239
  expect(self.cancel_button).to_be_visible()
@@ -28,9 +28,7 @@ class WorkflowDetailsPage(BasePage):
28
28
  @property
29
29
  def page_title(self) -> Locator:
30
30
  """Page title 'Workflow Details'."""
31
- return self.page.locator(
32
- 'div.text-lg.font-semibold:has-text("Workflow Details")'
33
- )
31
+ return self.page.locator('div.text-h3:has-text("Workflow Details")')
34
32
 
35
33
  @property
36
34
  def workflow_avatar(self) -> Locator:
@@ -40,7 +38,7 @@ class WorkflowDetailsPage(BasePage):
40
38
  @property
41
39
  def workflow_name(self) -> Locator:
42
40
  """Workflow name heading."""
43
- return self.page.locator('//main//div[contains(@class,"text-text-main")]')
41
+ return self.page.locator("h4.text-2xl ")
44
42
 
45
43
  @property
46
44
  def workflow_author(self) -> Locator:
@@ -62,9 +60,7 @@ class WorkflowDetailsPage(BasePage):
62
60
  @property
63
61
  def run_workflow_button(self) -> Locator:
64
62
  """Run workflow button."""
65
- return self.page.locator(
66
- 'button.button.primary.medium:has-text("Run workflow")'
67
- )
63
+ return self.page.locator('.button.primary.medium:has-text("Run workflow")')
68
64
 
69
65
  # Tab Elements
70
66
  @property
@@ -170,12 +166,9 @@ class WorkflowDetailsPage(BasePage):
170
166
  @property
171
167
  def about_workflow_section(self) -> Locator:
172
168
  """About workflow section."""
173
- return self.page.locator('div:has-text("About workflow:")').first
174
-
175
- @property
176
- def workflow_description(self) -> Locator:
177
- """Workflow description text."""
178
- return self.page.locator("div.text-sm.text-text-tertiary").first
169
+ return self.page.locator(
170
+ '//div[contains(text(),"About workflow:")]/following::div'
171
+ ).first
179
172
 
180
173
  @property
181
174
  def workflow_graph_schema_section(self) -> Locator:
@@ -190,7 +183,7 @@ class WorkflowDetailsPage(BasePage):
190
183
  @property
191
184
  def config_code_block(self) -> Locator:
192
185
  """Configuration code block container."""
193
- return self.page.locator("div.config div.code-block")
186
+ return self.page.locator("div.code-block > pre.code-content")
194
187
 
195
188
  @property
196
189
  def code_block_header(self) -> Locator:
@@ -205,12 +198,12 @@ class WorkflowDetailsPage(BasePage):
205
198
  @property
206
199
  def copy_code_button(self) -> Locator:
207
200
  """Copy code button."""
208
- return self.page.locator('button:has-text("Copy code")')
201
+ return self.page.locator('//button[normalize-space()="Copy"]')
209
202
 
210
203
  @property
211
204
  def download_code_button(self) -> Locator:
212
205
  """Download button."""
213
- return self.page.locator('button:has-text("Download")')
206
+ return self.page.locator('//button[normalize-space()="Download"]')
214
207
 
215
208
  @property
216
209
  def code_content(self) -> Locator:
@@ -228,11 +221,6 @@ class WorkflowDetailsPage(BasePage):
228
221
  """Overview title in sidebar."""
229
222
  return self.page.locator('span:has-text("OVERVIEW")').first
230
223
 
231
- @property
232
- def mode_info(self) -> Locator:
233
- """Mode information in sidebar."""
234
- return self.page.locator('div:has-text("Mode:")').first
235
-
236
224
  @property
237
225
  def project_info(self) -> Locator:
238
226
  """Project information in sidebar."""
@@ -240,15 +228,13 @@ class WorkflowDetailsPage(BasePage):
240
228
 
241
229
  @property
242
230
  def workflow_id_section(self) -> Locator:
243
- """Workflow ID section in sidebar."""
244
- return self.page.locator(
245
- '//div[text()="Workflow ID"]/following-sibling::label/div'
246
- )
231
+ """Workflow ID tab in Overview."""
232
+ return self.page.locator('//div[.="Workflow ID"]/following-sibling::label')
247
233
 
248
234
  @property
249
235
  def workflow_id_input(self) -> Locator:
250
236
  """Workflow ID input field."""
251
- return self.workflow_id_section.locator("//input[@disabled]")
237
+ return self.workflow_id_section.locator("//input[@readonly]")
252
238
 
253
239
  @property
254
240
  def workflow_id_copy_button(self) -> Locator:
@@ -256,28 +242,21 @@ class WorkflowDetailsPage(BasePage):
256
242
  return self.workflow_id_section.locator("//button")
257
243
 
258
244
  @property
259
- def access_links_section(self) -> Locator:
260
- """Access Links section in sidebar."""
261
- return self.page.locator(
262
- '//div[text()=" Access Links "]/following-sibling::label/div'
263
- )
245
+ def workflow_access_links_section(self) -> Locator:
246
+ """Workflow Access Links tab in Overview."""
247
+ return self.page.locator('//div[.="Access Links"]/following-sibling::label')
264
248
 
265
249
  @property
266
- def workflow_details_link_label(self) -> Locator:
267
- """Link to workflow details label."""
268
- return self.access_links_section.locator(
269
- '../preceding-sibling::div[text()="Link to workflow details:"]'
270
- )
250
+ def workflow_access_links_input(self) -> Locator:
251
+ """Workflow Access Links input field."""
252
+ return self.workflow_access_links_section.locator("//input[@readonly]")
271
253
 
272
254
  @property
273
- def workflow_details_link_input(self) -> Locator:
274
- """Workflow details link input field."""
275
- return self.access_links_section.locator("//input[@disabled]")
276
-
277
- @property
278
- def workflow_details_link_copy_button(self) -> Locator:
279
- """Copy button for workflow details link."""
280
- return self.access_links_section.locator("//button")
255
+ def workflow_access_links_copy_button(self) -> Locator:
256
+ """Copy button for workflow Access Links."""
257
+ return self.workflow_access_links_section.locator(
258
+ "//div[contains(@class, 'input-right-icon')]//button"
259
+ )
281
260
 
282
261
  # ==================== NAVIGATION METHODS ====================
283
262
 
@@ -540,7 +519,7 @@ class WorkflowDetailsPage(BasePage):
540
519
  """Verify that the Export popup is visible with expected content."""
541
520
  expect(self.pop_up.cancel).to_have_text("Cancel")
542
521
  expect(self.pop_up.submit).to_have_text("Export")
543
- expect(self.pop_up.header).to_have_text("Export Workflow Execution")
522
+ expect(self.pop_up.menu).to_have_text("Export Workflow Execution")
544
523
  expect(self.pop_up.close).to_be_visible()
545
524
 
546
525
  @step
@@ -554,7 +533,6 @@ class WorkflowDetailsPage(BasePage):
554
533
  def should_have_configuration_elements_visible(self):
555
534
  """Verify that all configuration tab elements are visible."""
556
535
  expect(self.about_workflow_section).to_be_visible()
557
- expect(self.workflow_description).to_be_visible()
558
536
  expect(self.workflow_graph_schema_section).to_be_visible()
559
537
  expect(self.workflow_graph_image).to_be_visible()
560
538
  expect(self.config_code_block).to_be_visible()
@@ -574,33 +552,26 @@ class WorkflowDetailsPage(BasePage):
574
552
  """Verify that overview sidebar is visible with all elements."""
575
553
  expect(self.overview_sidebar).to_be_visible()
576
554
  expect(self.overview_title).to_be_visible()
577
- expect(self.mode_info).to_be_visible()
578
555
  expect(self.project_info).to_be_visible()
579
556
 
580
557
  @step
581
558
  def should_have_workflow_id_section_visible(self):
582
559
  """Verify that workflow ID section is visible."""
583
560
  expect(self.workflow_id_section).to_be_visible()
561
+ expect(self.workflow_id_copy_button).to_be_visible()
584
562
  expect(self.workflow_id_input).to_be_visible()
585
- expect(self.workflow_id_input).to_be_disabled()
586
563
 
587
564
  @step
588
565
  def should_have_access_links_section_visible(self):
589
566
  """Verify that access links section is visible."""
590
- expect(self.access_links_section).to_be_visible()
591
- expect(self.workflow_details_link_label).to_be_visible()
592
- expect(self.workflow_details_link_input).to_be_visible()
593
- expect(self.workflow_details_link_input).to_be_disabled()
567
+ expect(self.workflow_access_links_section).to_be_visible()
568
+ expect(self.workflow_access_links_copy_button).to_be_visible()
569
+ expect(self.workflow_access_links_input).to_be_visible()
594
570
 
595
571
  @step
596
572
  def should_have_workflow_description(self, expected_description: str):
597
573
  """Verify the workflow description text."""
598
- expect(self.workflow_description).to_have_text(expected_description)
599
-
600
- @step
601
- def should_have_mode_value(self, expected_mode: str):
602
- """Verify the mode value in overview."""
603
- expect(self.mode_info).to_contain_text(expected_mode)
574
+ expect(self.about_workflow_section).to_have_text(expected_description)
604
575
 
605
576
  @step
606
577
  def should_have_project_value(self, expected_project: str):
@@ -615,8 +586,8 @@ class WorkflowDetailsPage(BasePage):
615
586
  @step
616
587
  def should_have_workflow_details_link_value(self, workflow_id: str):
617
588
  """Verify the workflow details link value."""
618
- expect(self.workflow_details_link_input).to_have_value(
619
- f"{os.getenv('UI_URL')}/#/workflows?workflow={workflow_id}"
589
+ expect(self.workflow_access_links_input).to_have_value(
590
+ f"{os.getenv('FRONTEND_URL')}#/workflows?workflow={workflow_id}"
620
591
  )
621
592
 
622
593
  @step
@@ -648,7 +619,7 @@ class WorkflowDetailsPage(BasePage):
648
619
  @step
649
620
  def click_copy_workflow_details_link(self):
650
621
  """Click the copy workflow details link button."""
651
- self.workflow_details_link_copy_button.click()
622
+ self.workflow_access_links_copy_button.click()
652
623
 
653
624
  @step
654
625
  def should_have_graph_image_loaded(self):