codemie-test-harness 0.1.171__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.

Files changed (21) hide show
  1. codemie_test_harness/tests/assistant/test_assistants.py +40 -0
  2. codemie_test_harness/tests/llm/assistants/test_lite_llm.py +8 -1
  3. codemie_test_harness/tests/test_data/files/test_extended.docx +0 -0
  4. codemie_test_harness/tests/ui/_test_data/__init__.py +0 -0
  5. codemie_test_harness/tests/ui/_test_data/assistant_test_data.py +1037 -0
  6. codemie_test_harness/tests/ui/_test_data/integration_test_data.py +121 -0
  7. codemie_test_harness/tests/ui/assistants/test_create_assistant.py +1 -1
  8. codemie_test_harness/tests/ui/conftest.py +25 -0
  9. codemie_test_harness/tests/ui/integrations/__init__.py +0 -0
  10. codemie_test_harness/tests/ui/integrations/test_create_integration.py +320 -0
  11. codemie_test_harness/tests/ui/pageobject/assistants/create_assistant_page.py +0 -20
  12. codemie_test_harness/tests/ui/pageobject/base_page.py +19 -6
  13. codemie_test_harness/tests/ui/pageobject/components/integration_row.py +299 -0
  14. codemie_test_harness/tests/ui/pageobject/integrations/create_integration_page.py +772 -0
  15. codemie_test_harness/tests/ui/pageobject/integrations/integrations_page.py +434 -0
  16. codemie_test_harness/tests/utils/credentials_manager.py +16 -0
  17. {codemie_test_harness-0.1.171.dist-info → codemie_test_harness-0.1.173.dist-info}/METADATA +2 -2
  18. {codemie_test_harness-0.1.171.dist-info → codemie_test_harness-0.1.173.dist-info}/RECORD +20 -12
  19. codemie_test_harness/tests/test_data/assistant_test_data.py +0 -596
  20. {codemie_test_harness-0.1.171.dist-info → codemie_test_harness-0.1.173.dist-info}/WHEEL +0 -0
  21. {codemie_test_harness-0.1.171.dist-info → codemie_test_harness-0.1.173.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,121 @@
1
+ """
2
+ Helper utilities for integration UI tests.
3
+ Contains reusable functions and data generators for integration testing.
4
+ """
5
+
6
+ from dataclasses import dataclass
7
+ from typing import Dict, Any
8
+
9
+ from codemie_sdk.models.integration import CredentialTypes
10
+
11
+ from codemie_test_harness.tests import PROJECT
12
+ from codemie_test_harness.tests.utils.base_utils import get_random_name
13
+
14
+
15
+ @dataclass
16
+ class IntegrationTestData:
17
+ """Data class for integration form fields."""
18
+
19
+ project: str
20
+ alias: str
21
+ description: str
22
+ credential_type: CredentialTypes
23
+ is_global: bool = False
24
+ fields: Dict[str, Any] = None
25
+
26
+ def __post_init__(self):
27
+ if self.fields is None:
28
+ self.fields = {}
29
+
30
+
31
+ class IntegrationTestDataFactory:
32
+ @staticmethod
33
+ def jira_integration() -> IntegrationTestData:
34
+ return IntegrationTestData(
35
+ project=PROJECT,
36
+ alias=f"JIRA Server Integration {get_random_name()}",
37
+ description="JIRA Server integration for project management",
38
+ credential_type=CredentialTypes.JIRA,
39
+ fields={
40
+ "url": "https://jira.company.com",
41
+ "username": "test.user@company.com",
42
+ "token": "secure_password",
43
+ },
44
+ )
45
+
46
+ @staticmethod
47
+ def jira_cloud_integration() -> IntegrationTestData:
48
+ return IntegrationTestData(
49
+ project=PROJECT,
50
+ alias=f"JIRA Cloud Integration {get_random_name()}",
51
+ description="JIRA Cloud integration with API token",
52
+ credential_type=CredentialTypes.JIRA,
53
+ fields={
54
+ "url": "https://jiraeu.epam.com",
55
+ "username": "test.user@company.com",
56
+ "token": "ATATT3xFfGF0...",
57
+ "is_cloud": True,
58
+ },
59
+ )
60
+
61
+ @staticmethod
62
+ def git_integration() -> IntegrationTestData:
63
+ return IntegrationTestData(
64
+ project=PROJECT,
65
+ alias=f"GitLab Integration {get_random_name()}",
66
+ description="GitLab integration for code repository access",
67
+ credential_type=CredentialTypes.GIT,
68
+ fields={
69
+ "url": "https://gitlab.company.com",
70
+ "token": "glpat-1234567890abcdef",
71
+ },
72
+ )
73
+
74
+ @staticmethod
75
+ def confluence_integration() -> IntegrationTestData:
76
+ return IntegrationTestData(
77
+ project=PROJECT,
78
+ alias=f"Confluence Integration {get_random_name()}",
79
+ description="Confluence integration for project management",
80
+ credential_type=CredentialTypes.CONFLUENCE,
81
+ fields={
82
+ "url": "https://kb.epam.com",
83
+ "username": "test.user@company.com",
84
+ "token": "secure_password",
85
+ "is_cloud": False,
86
+ },
87
+ )
88
+
89
+ @staticmethod
90
+ def confluence_cloud_integration() -> IntegrationTestData:
91
+ return IntegrationTestData(
92
+ project=PROJECT,
93
+ alias=f"Confluence Cloud Integration {get_random_name()}",
94
+ description="Confluence Cloud integration for project management",
95
+ credential_type=CredentialTypes.CONFLUENCE,
96
+ fields={
97
+ "url": "https://company.atlassian.net",
98
+ "username": "test.user@company.com",
99
+ "token": "ATATT3xFfGF0...",
100
+ "is_cloud": True,
101
+ },
102
+ )
103
+
104
+ # Expected validation messages
105
+ validation_messages = {
106
+ "invalid_email": "Please enter a valid email address",
107
+ "invalid_url": "Please enter a valid URL",
108
+ "duplicate_name": "An integration with this name already exists",
109
+ "connection_failed": "Connection test failed",
110
+ "connection_timeout": "Connection timeout",
111
+ "cannot_create_setting": "Cannot create specified setting",
112
+ "alias_required": "Alias is required",
113
+ }
114
+
115
+ # Success messages
116
+ success_messages = {
117
+ "integration_created": "Integration created successfully",
118
+ "integration_updated": "Integration updated successfully",
119
+ "connection_test_passed": "Connection test passed",
120
+ "integration_deleted": "Integration deleted successfully",
121
+ }
@@ -26,7 +26,7 @@ Architecture:
26
26
 
27
27
  import pytest
28
28
 
29
- from codemie_test_harness.tests.test_data.assistant_test_data import (
29
+ from codemie_test_harness.tests.ui._test_data.assistant_test_data import (
30
30
  get_minimal_assistant_data,
31
31
  )
32
32
  from codemie_test_harness.tests.ui.pageobject.assistants.assistants_page import (
@@ -4,6 +4,7 @@ from datetime import datetime
4
4
  from time import sleep
5
5
 
6
6
  import pytest
7
+ from codemie_sdk.models.integration import IntegrationType
7
8
  from reportportal_client import RPLogger, RPLogHandler
8
9
 
9
10
  from codemie_test_harness.tests import autotest_entity_prefix
@@ -96,6 +97,7 @@ def pytest_sessionfinish(session):
96
97
  clean_up_timeout = 1 if EnvironmentResolver.is_production() else 0
97
98
  client = get_client()
98
99
  prefix = autotest_entity_prefix
100
+ # Assistants
99
101
  assistants = client.assistants.list(filters={"search": prefix}, per_page=200)
100
102
  for assistant in assistants:
101
103
  if prefix in assistant.name:
@@ -105,3 +107,26 @@ def pytest_sessionfinish(session):
105
107
  for conversation in conversations:
106
108
  client.conversations.delete(conversation.id)
107
109
  sleep(clean_up_timeout)
110
+ # Integrations
111
+ integrations = client.integrations.list(
112
+ setting_type=IntegrationType.PROJECT,
113
+ filters={"search": autotest_entity_prefix},
114
+ per_page=200,
115
+ )
116
+ for integration in integrations:
117
+ if prefix in integration.alias:
118
+ client.integrations.delete(
119
+ setting_id=integration.id, setting_type=IntegrationType.PROJECT
120
+ )
121
+ sleep(clean_up_timeout)
122
+ integrations = client.integrations.list(
123
+ setting_type=IntegrationType.USER,
124
+ filters={"search": autotest_entity_prefix},
125
+ per_page=200,
126
+ )
127
+ for integration in integrations:
128
+ if prefix in integration.alias:
129
+ client.integrations.delete(
130
+ setting_id=integration.id, setting_type=IntegrationType.USER
131
+ )
132
+ sleep(clean_up_timeout)
File without changes
@@ -0,0 +1,320 @@
1
+ """
2
+ UI tests for Create Integration feature - critical paths with best practices.
3
+
4
+ This test suite covers the essential "Create Integration" workflow focusing on happy path scenarios.
5
+ All tests follow the Page Object Model pattern with reusable components abstracted in standalone classes.
6
+ """
7
+
8
+ import pytest
9
+ from codemie_sdk.models.integration import CredentialTypes
10
+
11
+ from codemie_test_harness.tests.ui._test_data.integration_test_data import (
12
+ IntegrationTestDataFactory,
13
+ )
14
+ from codemie_test_harness.tests.ui.pageobject.integrations.create_integration_page import (
15
+ CreateIntegrationPage,
16
+ )
17
+ from codemie_test_harness.tests.ui.pageobject.integrations.integrations_page import (
18
+ IntegrationsPage,
19
+ )
20
+
21
+
22
+ # noinspection PyArgumentList
23
+ class TestCreateIntegrationNavigation:
24
+ """Test class for integration creation navigation and page access."""
25
+
26
+ @pytest.mark.integration_ui
27
+ @pytest.mark.ui
28
+ @pytest.mark.smoke
29
+ def test_navigate_to_integrations_via_menu(self, page):
30
+ """
31
+ Test navigation to create integration page via menu.
32
+
33
+ Verifies:
34
+ - User can navigate to integrations page from menu
35
+ - Main UI elements are visible on Integrations page
36
+ """
37
+ # Arrange
38
+ integrations_page = IntegrationsPage(page)
39
+
40
+ # Act
41
+ integrations_page.navigate_to_via_menu()
42
+
43
+ # Assert
44
+ integrations_page.should_be_on_integrations_page()
45
+ integrations_page.should_see_create_integration_button()
46
+ integrations_page.should_see_integration_type_switcher()
47
+ integrations_page.should_see_integrations_table()
48
+
49
+ @pytest.mark.integration_ui
50
+ @pytest.mark.ui
51
+ @pytest.mark.smoke
52
+ def test_navigate_to_create_integration_via_direct_url(self, page):
53
+ """
54
+ Test direct navigation to create integration page via URL.
55
+
56
+ Verifies:
57
+ - Direct URL access works correctly
58
+ - Page Title matches integration type
59
+ """
60
+
61
+ create_integration_page = CreateIntegrationPage(page)
62
+
63
+ # Act
64
+ create_integration_page.navigate_to_user_integration_creation()
65
+
66
+ # Assert
67
+ create_integration_page.should_be_on_create_user_integration_page()
68
+
69
+ # Act
70
+ create_integration_page.navigate_to_project_integration_creation()
71
+
72
+ # Assert
73
+ create_integration_page.should_be_on_create_project_integration_page()
74
+
75
+ @pytest.mark.integration_ui
76
+ @pytest.mark.ui
77
+ @pytest.mark.smoke
78
+ def test_navigate_to_create_integration_from_integrations_page(self, page):
79
+ """
80
+ Test navigation to create integration page from integrations page ui elements.
81
+
82
+ Verifies:
83
+ - Navigation via UI elements works correctly
84
+ - Page Title matches integration type
85
+ """
86
+
87
+ integrations_page = IntegrationsPage(page)
88
+
89
+ # Navigate to User Integration creation
90
+ integrations_page.navigate_to().navigate_to_user_integration_creation()
91
+
92
+ create_integration_page = CreateIntegrationPage(page)
93
+
94
+ # Assert
95
+ create_integration_page.should_be_on_create_user_integration_page()
96
+
97
+ # Navigate to Project Integration creation
98
+ integrations_page.navigate_to().navigate_to_project_integration_creation()
99
+
100
+ # Assert
101
+ create_integration_page.should_be_on_create_project_integration_page()
102
+
103
+
104
+ # noinspection PyArgumentList
105
+ class TestIntegrationCreationPageElements:
106
+ """Test class for integration creation page elements display."""
107
+
108
+ @pytest.mark.integration_ui
109
+ @pytest.mark.ui
110
+ @pytest.mark.smoke
111
+ @pytest.mark.parametrize(
112
+ "credential_type",
113
+ [CredentialTypes.GIT, CredentialTypes.JIRA, CredentialTypes.CONFLUENCE],
114
+ )
115
+ def test_create_integration_type_form_fields(self, page, credential_type):
116
+ """
117
+ Test that all required form fields are displayed for Git credential type.
118
+
119
+ Verifies:
120
+ - Page navigation and structure validation
121
+ - Action buttons visibility (Back, Cancel, Create)
122
+ - Project selector element presence
123
+ - Global Integration toggle visibility
124
+ - Credential Type field with "Git" value
125
+ - Alias field with required indicator
126
+ - Authentication section with all fields (URL, Token name, Token)
127
+ - Help text and information tooltips
128
+ - Form field interactivity validation
129
+ - Create button initial disabled state
130
+ """
131
+
132
+ create_integration_page = CreateIntegrationPage(page)
133
+
134
+ # Act
135
+ create_integration_page.navigate_to_user_integration_creation()
136
+ create_integration_page.select_credential_type(credential_type)
137
+
138
+ # Assert - Verify page structure (includes title validation)
139
+ create_integration_page.should_be_on_create_user_integration_page()
140
+
141
+ # Assert - Verify UI elements visibility
142
+ (
143
+ create_integration_page.should_have_action_buttons_visible(credential_type)
144
+ .should_have_project_selector_visible()
145
+ .should_have_global_integration_toggle_visible()
146
+ .should_have_credential_type_field_visible()
147
+ .should_have_alias_field_visible()
148
+ .should_have_authentication_section_visible(credential_type)
149
+ .should_have_help_texts_visible()
150
+ )
151
+
152
+ # Assert - Verify credential type value
153
+ create_integration_page.should_have_credential_type_selected(credential_type)
154
+
155
+ # Assert - Verify form elements are interactive
156
+ create_integration_page.should_have_input_fields_editable()
157
+
158
+ # Assert - Verify Create button initial state
159
+ create_integration_page.should_have_create_button_enabled()
160
+
161
+
162
+ # noinspection PyArgumentList
163
+ class TestIntegrationCreationWorkflow:
164
+ """Test class for the complete integration creation workflow."""
165
+
166
+ @pytest.mark.integration_ui
167
+ @pytest.mark.ui
168
+ @pytest.mark.smoke
169
+ def test_create_git_integration_complete_workflow(self, page):
170
+ """
171
+ Test the complete Git integration creation workflow (happy path).
172
+
173
+ Verifies the end-to-end workflow for Git integration creation.
174
+ """
175
+ # Arrange
176
+ integrations_page = IntegrationsPage(page)
177
+ create_integration_page = CreateIntegrationPage(page)
178
+ integration_test_data = IntegrationTestDataFactory.git_integration()
179
+
180
+ # Act - Navigate and create
181
+ create_integration_page.navigate_to_user_integration_creation()
182
+ create_integration_page.fill_git_integration_form(integration_test_data)
183
+ create_integration_page.create_integration()
184
+
185
+ # Assert
186
+ (
187
+ integrations_page.navigate_to()
188
+ .should_see_message(
189
+ IntegrationTestDataFactory.success_messages["integration_created"]
190
+ )
191
+ .should_see_specific_integration(integration_test_data.alias)
192
+ )
193
+
194
+ @pytest.mark.integration_ui
195
+ @pytest.mark.ui
196
+ @pytest.mark.smoke
197
+ def test_create_jira_integration_complete_workflow(self, page):
198
+ """
199
+ Test the complete Jira integration creation workflow (happy path).
200
+
201
+ Verifies the end-to-end workflow for Jira integration creation including:
202
+ - Navigation to user integration creation page
203
+ - Credential type selection (Jira)
204
+ - Form filling with valid Jira integration data
205
+ - Integration creation and success validation
206
+ - Verification of created integration in integrations list
207
+ """
208
+ # Arrange
209
+ integrations_page = IntegrationsPage(page)
210
+ create_integration_page = CreateIntegrationPage(page)
211
+ integration_test_data = IntegrationTestDataFactory.jira_integration()
212
+
213
+ # Act - Navigate and create
214
+ create_integration_page.navigate_to_user_integration_creation()
215
+ create_integration_page.fill_jira_integration_form(integration_test_data)
216
+ create_integration_page.create_integration()
217
+
218
+ # Assert
219
+ (
220
+ integrations_page.navigate_to()
221
+ .should_see_message(
222
+ IntegrationTestDataFactory.success_messages["integration_created"]
223
+ )
224
+ .should_see_specific_integration(integration_test_data.alias)
225
+ )
226
+
227
+ @pytest.mark.integration_ui
228
+ @pytest.mark.ui
229
+ @pytest.mark.smoke
230
+ def test_create_confluence_integration_complete_workflow(self, page):
231
+ """
232
+ Test the complete Confluence integration creation workflow (happy path).
233
+
234
+ Verifies the end-to-end workflow for Confluence integration creation including:
235
+ - Navigation to user integration creation page
236
+ - Credential type selection (Confluence)
237
+ - Form filling with valid Confluence integration data
238
+ - Integration creation and success validation
239
+ - Verification of created integration in integrations list
240
+ """
241
+ # Arrange
242
+ integrations_page = IntegrationsPage(page)
243
+ create_integration_page = CreateIntegrationPage(page)
244
+ integration_test_data = IntegrationTestDataFactory.confluence_integration()
245
+
246
+ # Act - Navigate and create
247
+ create_integration_page.navigate_to_user_integration_creation()
248
+ create_integration_page.fill_confluence_integration_form(integration_test_data)
249
+ create_integration_page.create_integration()
250
+
251
+ # Assert
252
+ (
253
+ integrations_page.navigate_to()
254
+ .should_see_message(
255
+ IntegrationTestDataFactory.success_messages["integration_created"]
256
+ )
257
+ .should_see_specific_integration(integration_test_data.alias)
258
+ )
259
+
260
+
261
+ # noinspection PyArgumentList
262
+ class TestIntegrationFormUserExperience:
263
+ """Test class for integration form user experience and usability."""
264
+
265
+ @pytest.mark.integration_ui
266
+ @pytest.mark.ui
267
+ @pytest.mark.smoke
268
+ def test_form_reset_and_cancel_functionality(self, page):
269
+ """
270
+ Test form reset and cancel functionality.
271
+
272
+ Verifies:
273
+ - Cancel button navigates away from form
274
+ - Form data is not saved when cancelled
275
+ - User can safely exit creation process
276
+ """
277
+ # Arrange
278
+ create_integration_page = CreateIntegrationPage(page)
279
+ integrations_page = IntegrationsPage(page)
280
+
281
+ # Act
282
+ cancelled_integration_alias = "Test Integration to Cancel"
283
+ create_integration_page.navigate_to_user_integration_creation()
284
+ create_integration_page.fill_alias(cancelled_integration_alias)
285
+ create_integration_page.cancel_creation()
286
+
287
+ # Assert - Should navigate back to integrations page
288
+ integrations_page.should_have_page_title("Integrations")
289
+
290
+ # Verify the cancelled integration was not created
291
+ integrations_page.should_not_see_integration(cancelled_integration_alias)
292
+
293
+ @pytest.mark.integration_ui
294
+ @pytest.mark.ui
295
+ @pytest.mark.smoke
296
+ def test_alias_field_validation_message(self, page):
297
+ """
298
+ Test validation message when alias field is empty and form is submitted.
299
+
300
+ Verifies:
301
+ - Error toast notification appears with correct header
302
+ - Error message contains "Alias is required" text
303
+ - Toast notification is visible and readable
304
+ """
305
+ # Arrange
306
+ create_integration_page = CreateIntegrationPage(page)
307
+
308
+ # Act - Navigate to integration creation and try to submit without alias
309
+ create_integration_page.navigate_to_user_integration_creation()
310
+ create_integration_page.select_credential_type(CredentialTypes.GIT)
311
+ # Leave alias field empty intentionally
312
+ create_integration_page.create_integration()
313
+
314
+ # Assert - Verify error toast notification appears
315
+ create_integration_page.should_see_error_toast_message(
316
+ header=IntegrationTestDataFactory.validation_messages[
317
+ "cannot_create_setting"
318
+ ],
319
+ content=IntegrationTestDataFactory.validation_messages["alias_required"],
320
+ )
@@ -47,17 +47,6 @@ class CreateAssistantPage(BasePage):
47
47
  or self.page.locator('h1:has-text("Create Assistant")')
48
48
  )
49
49
 
50
- @property
51
- def back_button(self) -> Locator:
52
- """Back button in header with arrow icon"""
53
- return (
54
- self.page.locator("button.button.secondary.medium").first
55
- or self.page.locator(
56
- 'button:has(svg[xmlns="http://www.w3.org/2000/svg"])'
57
- ).first
58
- or self.page.locator(".mr-6 button")
59
- )
60
-
61
50
  @property
62
51
  def generate_with_ai_button(self) -> Locator:
63
52
  """Generate with AI button in header with magical styling"""
@@ -71,15 +60,6 @@ class CreateAssistantPage(BasePage):
71
60
  )
72
61
  )
73
62
 
74
- @property
75
- def cancel_button(self) -> Locator:
76
- """Cancel button in header"""
77
- return (
78
- self.page.locator('button.button.secondary.medium:has-text("Cancel")')
79
- or self.page.locator('button:has-text("Cancel")')
80
- or self.page.locator('.ml-auto button:has-text("Cancel")')
81
- )
82
-
83
63
  @property
84
64
  def create_button(self) -> Locator:
85
65
  """Create button with plus icon (primary button)"""
@@ -1,6 +1,6 @@
1
1
  import re
2
2
 
3
- from playwright.sync_api import expect
3
+ from playwright.sync_api import expect, Locator
4
4
  from reportportal_client import step
5
5
 
6
6
  from codemie_test_harness.tests.ui.pageobject.components.menu import Menu
@@ -15,11 +15,24 @@ class BasePage:
15
15
 
16
16
  # Component properties using @property decorator
17
17
  @property
18
- def back_button(self):
19
- """Back button in the menu."""
20
- return self.page.locator(
21
- '//div[not(contains(@class,"justify-end"))]/button[contains(@class,"secondary medium")]'
22
- ).first
18
+ def back_button(self) -> Locator:
19
+ """Back button in header with arrow icon"""
20
+ return (
21
+ self.page.locator("button.button.secondary.medium").first
22
+ or self.page.locator(
23
+ 'button:has(svg[xmlns="http://www.w3.org/2000/svg"])'
24
+ ).first
25
+ or self.page.locator(".mr-6 button")
26
+ )
27
+
28
+ @property
29
+ def cancel_button(self) -> Locator:
30
+ """Cancel button in header"""
31
+ return (
32
+ self.page.locator('button.button.secondary.medium:has-text("Cancel")')
33
+ or self.page.locator('button:has-text("Cancel")')
34
+ or self.page.locator('.ml-auto button:has-text("Cancel")')
35
+ )
23
36
 
24
37
  @property
25
38
  def pop_up(self):