codemie-test-harness 0.1.172__py3-none-any.whl → 0.1.173__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/_test_data/__init__.py +0 -0
- codemie_test_harness/tests/ui/_test_data/integration_test_data.py +121 -0
- codemie_test_harness/tests/ui/assistants/test_create_assistant.py +1 -1
- codemie_test_harness/tests/ui/conftest.py +25 -0
- codemie_test_harness/tests/ui/integrations/__init__.py +0 -0
- codemie_test_harness/tests/ui/integrations/test_create_integration.py +320 -0
- codemie_test_harness/tests/ui/pageobject/assistants/create_assistant_page.py +0 -20
- codemie_test_harness/tests/ui/pageobject/base_page.py +19 -6
- codemie_test_harness/tests/ui/pageobject/components/integration_row.py +299 -0
- codemie_test_harness/tests/ui/pageobject/integrations/create_integration_page.py +772 -0
- codemie_test_harness/tests/ui/pageobject/integrations/integrations_page.py +434 -0
- {codemie_test_harness-0.1.172.dist-info → codemie_test_harness-0.1.173.dist-info}/METADATA +2 -2
- {codemie_test_harness-0.1.172.dist-info → codemie_test_harness-0.1.173.dist-info}/RECORD +16 -9
- /codemie_test_harness/tests/{test_data → ui/_test_data}/assistant_test_data.py +0 -0
- {codemie_test_harness-0.1.172.dist-info → codemie_test_harness-0.1.173.dist-info}/WHEEL +0 -0
- {codemie_test_harness-0.1.172.dist-info → codemie_test_harness-0.1.173.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integration card component for individual integration items.
|
|
3
|
+
Contains methods for interacting with integration cards in the integrations list.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from playwright.sync_api import expect, Locator
|
|
7
|
+
from reportportal_client import step
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class IntegrationRow:
|
|
11
|
+
"""Integration card component with property-based element locators."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, page, card_locator: Locator):
|
|
14
|
+
self.page = page
|
|
15
|
+
self.card = card_locator
|
|
16
|
+
|
|
17
|
+
# Card element properties
|
|
18
|
+
@property
|
|
19
|
+
def card_container(self):
|
|
20
|
+
"""The main card container."""
|
|
21
|
+
return self.card
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def integration_name(self):
|
|
25
|
+
"""Integration name/title element."""
|
|
26
|
+
return self.card.locator(
|
|
27
|
+
'.integration-name, .card-title, h3, [data-testid="integration-name"]'
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def integration_type(self):
|
|
32
|
+
"""Integration type/category element."""
|
|
33
|
+
return self.card.locator(
|
|
34
|
+
'.integration-type, .card-subtitle, .type-badge, [data-testid="integration-type"]'
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def integration_icon(self):
|
|
39
|
+
"""Integration icon/logo element."""
|
|
40
|
+
return self.card.locator(
|
|
41
|
+
'.integration-icon, .card-icon, img, svg, [data-testid="integration-icon"]'
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def status_indicator(self):
|
|
46
|
+
"""Integration status indicator (active/inactive/error)."""
|
|
47
|
+
return self.card.locator(
|
|
48
|
+
'.status-indicator, .status-badge, [data-testid="status"]'
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def description(self):
|
|
53
|
+
"""Integration description text."""
|
|
54
|
+
return self.card.locator(
|
|
55
|
+
'.integration-description, .card-description, [data-testid="description"]'
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def created_date(self):
|
|
60
|
+
"""Integration creation date."""
|
|
61
|
+
return self.card.locator(
|
|
62
|
+
'.created-date, .date-created, [data-testid="created-date"]'
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def last_used_date(self):
|
|
67
|
+
"""Last used date."""
|
|
68
|
+
return self.card.locator('.last-used, .date-used, [data-testid="last-used"]')
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def checkbox(self):
|
|
72
|
+
"""Selection checkbox."""
|
|
73
|
+
return self.card.locator(
|
|
74
|
+
'input[type="checkbox"], [data-testid="select-checkbox"]'
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def menu_button(self):
|
|
79
|
+
"""Card menu button (three dots)."""
|
|
80
|
+
return self.card.locator(
|
|
81
|
+
'.menu-button, button[aria-label*="menu"], [data-testid="menu-btn"]'
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def edit_button(self):
|
|
86
|
+
"""Edit integration button."""
|
|
87
|
+
return self.card.locator('button:has-text("Edit"), [data-testid="edit-btn"]')
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def delete_button(self):
|
|
91
|
+
"""Delete integration button."""
|
|
92
|
+
return self.card.locator(
|
|
93
|
+
'button:has-text("Delete"), [data-testid="delete-btn"]'
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def test_connection_button(self):
|
|
98
|
+
"""Test connection button."""
|
|
99
|
+
return self.card.locator(
|
|
100
|
+
'button:has-text("Test"), button:has-text("Test Connection"), [data-testid="test-btn"]'
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def duplicate_button(self):
|
|
105
|
+
"""Duplicate integration button."""
|
|
106
|
+
return self.card.locator(
|
|
107
|
+
'button:has-text("Duplicate"), [data-testid="duplicate-btn"]'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def view_details_button(self):
|
|
112
|
+
"""View details button."""
|
|
113
|
+
return self.card.locator(
|
|
114
|
+
'button:has-text("Details"), button:has-text("View"), [data-testid="details-btn"]'
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def share_button(self):
|
|
119
|
+
"""Share integration button."""
|
|
120
|
+
return self.card.locator('button:has-text("Share"), [data-testid="share-btn"]')
|
|
121
|
+
|
|
122
|
+
# Context menu properties
|
|
123
|
+
@property
|
|
124
|
+
def context_menu(self):
|
|
125
|
+
"""Context menu that appears when clicking the menu button."""
|
|
126
|
+
return self.page.locator(
|
|
127
|
+
'.context-menu, .dropdown-menu, [data-testid="context-menu"]'
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def context_menu_edit(self):
|
|
132
|
+
"""Edit option in context menu."""
|
|
133
|
+
return self.context_menu.locator(
|
|
134
|
+
'button:has-text("Edit"), [data-testid="context-edit"]'
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def context_menu_delete(self):
|
|
139
|
+
"""Delete option in context menu."""
|
|
140
|
+
return self.context_menu.locator(
|
|
141
|
+
'button:has-text("Delete"), [data-testid="context-delete"]'
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def context_menu_test(self):
|
|
146
|
+
"""Test connection option in context menu."""
|
|
147
|
+
return self.context_menu.locator(
|
|
148
|
+
'button:has-text("Test"), [data-testid="context-test"]'
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def context_menu_duplicate(self):
|
|
153
|
+
"""Duplicate option in context menu."""
|
|
154
|
+
return self.context_menu.locator(
|
|
155
|
+
'button:has-text("Duplicate"), [data-testid="context-duplicate"]'
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Action methods
|
|
159
|
+
@step
|
|
160
|
+
def click(self):
|
|
161
|
+
"""Click on the integration card."""
|
|
162
|
+
self.card_container.click()
|
|
163
|
+
return self
|
|
164
|
+
|
|
165
|
+
@step
|
|
166
|
+
def hover(self):
|
|
167
|
+
"""Hover over the integration card."""
|
|
168
|
+
self.card_container.hover()
|
|
169
|
+
return self
|
|
170
|
+
|
|
171
|
+
@step
|
|
172
|
+
def select(self):
|
|
173
|
+
"""Select the integration by checking its checkbox."""
|
|
174
|
+
if self.checkbox.is_visible():
|
|
175
|
+
self.checkbox.check()
|
|
176
|
+
return self
|
|
177
|
+
|
|
178
|
+
@step
|
|
179
|
+
def deselect(self):
|
|
180
|
+
"""Deselect the integration by unchecking its checkbox."""
|
|
181
|
+
if self.checkbox.is_visible():
|
|
182
|
+
self.checkbox.uncheck()
|
|
183
|
+
return self
|
|
184
|
+
|
|
185
|
+
@step
|
|
186
|
+
def click_menu(self):
|
|
187
|
+
"""Click the menu button to open context menu."""
|
|
188
|
+
self.menu_button.click()
|
|
189
|
+
return self
|
|
190
|
+
|
|
191
|
+
@step
|
|
192
|
+
def click_edit(self):
|
|
193
|
+
"""Click the edit button."""
|
|
194
|
+
if self.edit_button.is_visible():
|
|
195
|
+
self.edit_button.click()
|
|
196
|
+
else:
|
|
197
|
+
self.click_menu()
|
|
198
|
+
self.context_menu_edit.click()
|
|
199
|
+
return self
|
|
200
|
+
|
|
201
|
+
@step
|
|
202
|
+
def click_delete(self):
|
|
203
|
+
"""Click the delete button."""
|
|
204
|
+
if self.delete_button.is_visible():
|
|
205
|
+
self.delete_button.click()
|
|
206
|
+
else:
|
|
207
|
+
self.click_menu()
|
|
208
|
+
self.context_menu_delete.click()
|
|
209
|
+
return self
|
|
210
|
+
|
|
211
|
+
@step
|
|
212
|
+
def click_test_connection(self):
|
|
213
|
+
"""Click the test connection button."""
|
|
214
|
+
if self.test_connection_button.is_visible():
|
|
215
|
+
self.test_connection_button.click()
|
|
216
|
+
else:
|
|
217
|
+
self.click_menu()
|
|
218
|
+
self.context_menu_test.click()
|
|
219
|
+
return self
|
|
220
|
+
|
|
221
|
+
@step
|
|
222
|
+
def click_view_details(self):
|
|
223
|
+
"""Click the view details button."""
|
|
224
|
+
self.view_details_button.click()
|
|
225
|
+
return self
|
|
226
|
+
|
|
227
|
+
@step
|
|
228
|
+
def click_share(self):
|
|
229
|
+
"""Click the share button."""
|
|
230
|
+
self.share_button.click()
|
|
231
|
+
return self
|
|
232
|
+
|
|
233
|
+
# Information retrieval methods
|
|
234
|
+
@step
|
|
235
|
+
def get_integration_name(self) -> str:
|
|
236
|
+
"""
|
|
237
|
+
Get the integration name.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
str: The integration name
|
|
241
|
+
"""
|
|
242
|
+
return self.integration_name.text_content().strip()
|
|
243
|
+
|
|
244
|
+
@step
|
|
245
|
+
def get_integration_type(self) -> str:
|
|
246
|
+
"""
|
|
247
|
+
Get the integration type.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
str: The integration type
|
|
251
|
+
"""
|
|
252
|
+
return self.integration_type.text_content().strip()
|
|
253
|
+
|
|
254
|
+
@step
|
|
255
|
+
def is_selected(self) -> bool:
|
|
256
|
+
"""
|
|
257
|
+
Check if the integration is selected.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
bool: True if selected, False otherwise
|
|
261
|
+
"""
|
|
262
|
+
if self.checkbox.is_visible():
|
|
263
|
+
return self.checkbox.is_checked()
|
|
264
|
+
return False
|
|
265
|
+
|
|
266
|
+
# Verification methods
|
|
267
|
+
@step
|
|
268
|
+
def should_be_visible(self):
|
|
269
|
+
"""Verify that the integration card is visible."""
|
|
270
|
+
expect(self.card_container).to_be_visible()
|
|
271
|
+
return self
|
|
272
|
+
|
|
273
|
+
@step
|
|
274
|
+
def should_be_hidden(self):
|
|
275
|
+
"""Verify that the integration card is hidden."""
|
|
276
|
+
expect(self.card_container).to_be_hidden()
|
|
277
|
+
return self
|
|
278
|
+
|
|
279
|
+
@step
|
|
280
|
+
def should_have_name(self, expected_name: str):
|
|
281
|
+
"""
|
|
282
|
+
Verify the integration name.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
expected_name (str): Expected integration name
|
|
286
|
+
"""
|
|
287
|
+
expect(self.integration_name).to_contain_text(expected_name)
|
|
288
|
+
return self
|
|
289
|
+
|
|
290
|
+
@step
|
|
291
|
+
def should_have_type(self, expected_type: str):
|
|
292
|
+
"""
|
|
293
|
+
Verify the integration type.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
expected_type (str): Expected integration type
|
|
297
|
+
"""
|
|
298
|
+
expect(self.integration_type).to_contain_text(expected_type)
|
|
299
|
+
return self
|