codemie-test-harness 0.1.205__py3-none-any.whl → 0.1.207__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 (25) hide show
  1. codemie_test_harness/tests/assistant/datasource/test_code_datasource.py +2 -2
  2. codemie_test_harness/tests/assistant/tools/git/test_assistant_with_git_tools.py +14 -14
  3. codemie_test_harness/tests/conftest.py +34 -12
  4. codemie_test_harness/tests/e2e/test_e2e.py +2 -2
  5. codemie_test_harness/tests/ui/assistants/test_create_assistant.py +13 -13
  6. codemie_test_harness/tests/ui/assistants/test_edit_assistant.py +200 -0
  7. codemie_test_harness/tests/ui/datasource/test_create_datasource.py +2 -2
  8. codemie_test_harness/tests/ui/datasource/test_edit_datasource.py +2 -2
  9. codemie_test_harness/tests/ui/datasource/test_view_datasource.py +2 -2
  10. codemie_test_harness/tests/ui/pageobject/assistants/assistant_mcp_server.py +171 -0
  11. codemie_test_harness/tests/ui/pageobject/assistants/assistant_sidebar.py +140 -0
  12. codemie_test_harness/tests/ui/pageobject/assistants/assistant_view_page.py +256 -0
  13. codemie_test_harness/tests/ui/pageobject/assistants/assistants_page.py +63 -0
  14. codemie_test_harness/tests/ui/pageobject/assistants/{create_assistant_page.py → create_edit_assistant_page.py} +379 -95
  15. codemie_test_harness/tests/ui/test_data/assistant_test_data.py +347 -18
  16. codemie_test_harness/tests/utils/constants.py +1 -1
  17. codemie_test_harness/tests/utils/webhook_utils.py +10 -0
  18. codemie_test_harness/tests/webhook/__init__.py +0 -0
  19. codemie_test_harness/tests/webhook/test_webhook_service.py +225 -0
  20. codemie_test_harness/tests/workflow/assistant_tools/git/test_workflow_with_assistant_git_tools.py +14 -14
  21. codemie_test_harness/tests/workflow/virtual_assistant_tools/git/test_workflow_with_git_tools.py +14 -14
  22. {codemie_test_harness-0.1.205.dist-info → codemie_test_harness-0.1.207.dist-info}/METADATA +2 -2
  23. {codemie_test_harness-0.1.205.dist-info → codemie_test_harness-0.1.207.dist-info}/RECORD +25 -18
  24. {codemie_test_harness-0.1.205.dist-info → codemie_test_harness-0.1.207.dist-info}/WHEEL +0 -0
  25. {codemie_test_harness-0.1.205.dist-info → codemie_test_harness-0.1.207.dist-info}/entry_points.txt +0 -0
@@ -8,6 +8,7 @@ reusable data factories for consistent testing.
8
8
 
9
9
  from dataclasses import dataclass
10
10
  from typing import Optional, List
11
+ from enum import Enum
11
12
 
12
13
  from codemie_test_harness.tests.utils.base_utils import get_random_name
13
14
 
@@ -28,6 +29,24 @@ class AssistantTestData:
28
29
  shared: bool = False
29
30
 
30
31
 
32
+ @dataclass
33
+ class AssistantMCPConfigTestData:
34
+ """
35
+ Data class for assistant MCP config test data.
36
+
37
+ This class encapsulates all the data needed for assistant creation tests,
38
+ providing a clean and type-safe way to manage test data.
39
+ """
40
+
41
+ name: str
42
+ description: str
43
+ configuration: str
44
+ token_size_limit: Optional[str] = None
45
+ configuration_type: Optional[bool] = False
46
+ env_var: Optional[str] = None
47
+ mcp_url: Optional[str] = None
48
+
49
+
31
50
  class AssistantTestDataFactory:
32
51
  """
33
52
  Factory class for generating assistant test data.
@@ -117,7 +136,33 @@ class AssistantTestDataFactory:
117
136
  ]
118
137
 
119
138
 
120
- class AssistantValidationRules:
139
+ class AssistantMCPTestDataFactory:
140
+ """
141
+ Factory class for generating assistant test data for creating new MCP server..
142
+
143
+ This factory provides various methods to create different types of
144
+ assistant test data for different testing scenarios.
145
+ """
146
+
147
+ @staticmethod
148
+ def create_minimal_assistant_mcp_data() -> AssistantMCPConfigTestData:
149
+ """
150
+ Create minimal assistant data with only required fields.
151
+
152
+ This represents the most basic assistant creation scenario
153
+ with minimal required information.
154
+
155
+ Returns:
156
+ AssistantMCPTestDataFactory: Minimal assistant mcp config test data
157
+ """
158
+ return AssistantMCPConfigTestData(
159
+ name="MCP Test",
160
+ description="MCP for test purposes",
161
+ configuration='{"command": "test"}',
162
+ )
163
+
164
+
165
+ class AssistantValidationErrors(Enum):
121
166
  """
122
167
  Validation rules and constraints for assistant data.
123
168
 
@@ -125,24 +170,30 @@ class AssistantValidationRules:
125
170
  to assistant data during testing.
126
171
  """
127
172
 
128
- # Field length constraints
129
- MAX_NAME_LENGTH = 100
130
- MAX_DESCRIPTION_LENGTH = 1000
131
- MAX_ICON_URL_LENGTH = 500
173
+ NAME_REQUIRED = "Name is required"
174
+ ICON_URL_NOT_VALID = "Icon URL must be a valid URL"
175
+ DESCRIPTION_REQUIRED = "Description is required"
176
+ SYSTEM_PROMPT_REQUIRED = "System instructions are required"
177
+ TEMPERATURE_NOT_VALID = "Temperature must be at most 2"
178
+ TOP_P_NOT_VALID = "Top P must be at most 1"
132
179
 
133
- # Required fields
134
- REQUIRED_FIELDS = ["name", "description", "system_prompt"]
135
180
 
136
- # Validation error messages (expected messages for testing)
137
- ERROR_MESSAGES = {
138
- "name_required": "Name is required",
139
- "name_too_long": f"Name must be less than {MAX_NAME_LENGTH} characters",
140
- "description_required": "Description is required",
141
- "description_too_long": f"Description must be less than {MAX_DESCRIPTION_LENGTH} characters",
142
- "system_prompt_required": "System prompt is required",
143
- "invalid_url": "Please enter a valid URL",
144
- "invalid_type": "Please select a valid assistant type",
145
- }
181
+ class AssistantPopUpMessages(Enum):
182
+ """
183
+ Enumerates expected popup notification and toast messages for assistant actions in UI tests.
184
+
185
+ This enum class should include all standardized popup/toast messages
186
+ that are expected to appear as a result of user workflow, such as
187
+ success/error messages after saving or updating an assistant,
188
+ deletion confirmations, or integration test results.
189
+
190
+ Using this enum in UI tests ensures message checks are maintainable,
191
+ consistent, and robust against typo errors or message changes.
192
+ """
193
+
194
+ ASSISTANT_UPDATED_SUCCESS = "Assistant has been updated successfully!"
195
+ ASSISTANT_CREATED_SUCCESS = "Assistant has been created successfully!"
196
+ ASSISTANT_DELETED_SUCCESS = "Assistant has been deleted successfully!"
146
197
 
147
198
 
148
199
  # ==================== CONVENIENCE FUNCTIONS ====================
@@ -163,6 +214,11 @@ def get_validation_test_data() -> List[AssistantTestData]:
163
214
  return AssistantTestDataFactory.create_validation_test_data()
164
215
 
165
216
 
217
+ def get_minimal_assistant_mcp_config_data() -> AssistantMCPConfigTestData:
218
+ """Convenience function to get minimal assistant mcp config test data."""
219
+ return AssistantMCPTestDataFactory.create_minimal_assistant_mcp_data()
220
+
221
+
166
222
  # ==================== TEST DATA CONSTANTS ====================
167
223
 
168
224
  # Common test values for reuse
@@ -196,4 +252,277 @@ COMMON_ICON_URLS = {
196
252
 
197
253
  ICON_URL = "https://raw.githubusercontent.com/epam-gen-ai-run/ai-run-install/main/docs/assets/ai/AQAUiTestGenerator.png"
198
254
 
199
- GENERAL_PROMPT = "You are a helpful integration test assistant"
255
+
256
+ # ==================== ASSISTANT TOOLS CONSTANTS ====================
257
+ class Section(Enum):
258
+ AVAILABLE_TOOLS = "Available Tools"
259
+ EXTERNAL_TOOLS = "External Tools"
260
+
261
+
262
+ class Toolkit(Enum):
263
+ GIT = "Git"
264
+ VCS = "VCS"
265
+ CODEBASE_TOOLS = "Codebase Tools"
266
+ RESEARCH = "Research"
267
+ CLOUD = "Cloud"
268
+ AZURE_DEVOPS_WIKI = "Azure DevOps Wiki"
269
+ AZURE_DEVOPS_WORK_ITEM = "Azure DevOps Work Item"
270
+ AZURE_DEVOPS_TEST_PLAN = "Azure DevOps Test Plan"
271
+ ACCESS_MANAGEMENT = "Access Management"
272
+ PROJECT_MANAGEMENT = "Project Management"
273
+ PLUGIN = "Plugin"
274
+ OPEN_API = "OpenAPI"
275
+ NOTIFICATION = "Notification"
276
+ DATA_MANAGEMENT = "Data Management"
277
+ FILE_MANAGEMENT = "File Management"
278
+ QUALITY_ASSURANCE = "Quality Assurance"
279
+ REPORT_PORTAL = "Report Portal"
280
+ IT_SERVICE_MANAGEMENT = "IT Service Management"
281
+
282
+
283
+ class ExternalToolKit(Enum):
284
+ MCP_SERVERS = "MCP Servers"
285
+
286
+
287
+ class GitTool(Enum):
288
+ CREATE_BRANCH = "Create Branch"
289
+ SET_ACTIVE_BRANCH = "Set Active Branch"
290
+ LIST_BRANCHES_IN_REPO = "List Branches In Repo"
291
+ CREATE_FILE = "Create File"
292
+ UPDATE_FILE = "Update File"
293
+ UPDATE_FILE_DIFF = "Update File Diff"
294
+ DELETE_FILE = "Delete File"
295
+ CREATE_PULL_REQUEST = "Create Pull/Merge request"
296
+ GET_PR_CHANGES = "Get Pull/Merge Request Changes"
297
+ CREATE_PR_CHANGE_COMMENT = "Create Pull/Merge Request Change Comment"
298
+
299
+
300
+ class VcsTool(Enum):
301
+ GITHUB = "Github"
302
+ GITLAB = "Gitlab"
303
+
304
+
305
+ class CodebaseTool(Enum):
306
+ GET_REPOSITORY_FILE_TREE_V2 = "Get Repo Tree with filtering (Experimental)"
307
+ SEARCH_CODE_REPO_V2 = "Search Code with filtering (Experimental)"
308
+ READ_FILES_CONTENT = "Read Files Content"
309
+ READ_FILES_CONTENT_SUMMARY = "Read Files Content With Summary For Large"
310
+ SEARCH_CODE_REPO_BY_PATH = "Search Code Repo By Path"
311
+ SONAR = "Sonar"
312
+
313
+
314
+ class ResearchTool(Enum):
315
+ GOOGLE_SEARCH = "Google Search"
316
+ GOOGLE_PLACES = "Google Places"
317
+ GOOGLE_PLACES_FIND_NEAR = "Google Places Find Near"
318
+ WIKIPEDIA = "Wikipedia"
319
+ TAVILY_SEARCH = "Tavily Search"
320
+ WEB_SCRAPPER = "Web Scraper"
321
+
322
+
323
+ class CloudTool(Enum):
324
+ KUBERNETES = "Kubernetes"
325
+ AWS = "AWS"
326
+ GCP = "GCP"
327
+ AZURE = "Azure"
328
+
329
+
330
+ class AzureDevOpsWikiTool(Enum):
331
+ GET_WIKI = "Get Wiki"
332
+ GET_WIKI_PAGE_BY_PATH = "Get Wiki Page By Path"
333
+ GET_WIKI_PAGE_BY_ID = "Get Wiki Page By ID"
334
+ DELETE_PAGE_BY_PATH = "Delete Wiki Page By Path"
335
+ DELETE_PAGE_BY_ID = "Delete Wiki Page By ID"
336
+ MODIFY_WIKI_PAGE = "Modify Wiki Page"
337
+ RENAME_WIKI_PAGE = "Rename Wiki Page"
338
+
339
+
340
+ class AzureDevOpsWorkItemTool(Enum):
341
+ SEARCH_WORK_ITEMS = "Search Work Items"
342
+ CREATE_WORK_ITEM = "Create Work Item"
343
+ UPDATE_WORK_ITEM = "Update Work Item"
344
+ GET_WORK_ITEM = "Get Work Item"
345
+ LINK_WORK_ITEMS = "Link Work Items"
346
+ GET_RELATION_TYPES = "Get Relation Types"
347
+ GET_COMMENTS = "Get Comments"
348
+
349
+
350
+ class AzureDevOpsTestPlanTool(Enum):
351
+ CREATE_TEST_PLAN = "Create Test Plan"
352
+ DELETE_TEST_PLAN = "Delete Test Plan"
353
+ GET_TEST_PLAN = "Get Test Plan"
354
+ CREATE_TEST_SUITE = "Create Test Suite"
355
+ DELETE_TEST_SUITE = "Delete Test Suite"
356
+ GET_TEST_SUITE = "Get Test Suite"
357
+ ADD_TEST_CASE = "Add Test Case"
358
+ GET_TEST_CASE = "Get Test Case"
359
+ GET_TEST_CASES = "Get Test Cases"
360
+
361
+
362
+ class AccessManagementTool(Enum):
363
+ KEYCLOAK = "Keycloak"
364
+
365
+
366
+ class ProjectManagementTool(Enum):
367
+ GENERIC_JIRA = "Generic Jira"
368
+ GENERIC_CONFLUENCE = "Generic Confluence"
369
+
370
+
371
+ class PluginTool(Enum):
372
+ PLUGIN = "Plugin"
373
+
374
+
375
+ class OpenAPITool(Enum):
376
+ INVOKE_EXTERNAL_API = "Invoke external API"
377
+ GET_OPEN_API_SPEC = "Get Open API spec"
378
+
379
+
380
+ class NotificationTool(Enum):
381
+ EMAIL = "Email"
382
+ TELEGRAM = "Telegram"
383
+
384
+
385
+ class DataManagementTool(Enum):
386
+ ELASTIC = "Search Elastic index"
387
+ SQL = "SQL"
388
+
389
+
390
+ class FileManagementTool(Enum):
391
+ READ_FILE = "Read file"
392
+ WRITE_FILE = "Write file"
393
+ LIST_DIRECTORY = "List directory"
394
+ RUN_COMMAND_LINE = "Run command line"
395
+ CODE_INTERPRETER = "Code Interpreter"
396
+ GENERATE_IMAGE_TOOL = "Generate image"
397
+ DIFF_UPDATE_FILE_TOOL = "Read Generate Update File (diff)"
398
+ STR_REPLACE_EDITOR = "Filesystem Editor Tool"
399
+
400
+
401
+ class QualityAssuranceTool(Enum):
402
+ ZEPHYR_SCALE = "Zephyr Scale"
403
+ ZEPHYR_SQUAD = "Zephyr Squad"
404
+
405
+
406
+ class ITServiceManagementTool(Enum):
407
+ SERVICENOW_TABLE_API = "ServiceNow Table API"
408
+
409
+
410
+ class MCPServersTool(Enum):
411
+ ADD_MCP_SERVER = " Add MCP Server "
412
+
413
+
414
+ TOOLKIT_TOOLS = {
415
+ Section.AVAILABLE_TOOLS: {
416
+ Toolkit.GIT: [
417
+ GitTool.CREATE_BRANCH,
418
+ GitTool.SET_ACTIVE_BRANCH,
419
+ GitTool.LIST_BRANCHES_IN_REPO,
420
+ GitTool.CREATE_FILE,
421
+ GitTool.UPDATE_FILE,
422
+ GitTool.UPDATE_FILE_DIFF,
423
+ GitTool.DELETE_FILE,
424
+ GitTool.CREATE_PULL_REQUEST,
425
+ GitTool.GET_PR_CHANGES,
426
+ GitTool.CREATE_PR_CHANGE_COMMENT,
427
+ ],
428
+ Toolkit.VCS: [
429
+ VcsTool.GITHUB,
430
+ VcsTool.GITLAB,
431
+ ],
432
+ Toolkit.CODEBASE_TOOLS: [
433
+ CodebaseTool.GET_REPOSITORY_FILE_TREE_V2,
434
+ CodebaseTool.SEARCH_CODE_REPO_V2,
435
+ CodebaseTool.READ_FILES_CONTENT,
436
+ CodebaseTool.READ_FILES_CONTENT_SUMMARY,
437
+ CodebaseTool.SEARCH_CODE_REPO_BY_PATH,
438
+ CodebaseTool.SONAR,
439
+ ],
440
+ Toolkit.RESEARCH: [
441
+ ResearchTool.GOOGLE_SEARCH,
442
+ ResearchTool.GOOGLE_PLACES,
443
+ ResearchTool.GOOGLE_PLACES_FIND_NEAR,
444
+ ResearchTool.WIKIPEDIA,
445
+ ResearchTool.TAVILY_SEARCH,
446
+ ResearchTool.WEB_SCRAPPER,
447
+ ],
448
+ Toolkit.CLOUD: [
449
+ CloudTool.KUBERNETES,
450
+ CloudTool.AWS,
451
+ CloudTool.GCP,
452
+ CloudTool.AZURE,
453
+ ],
454
+ Toolkit.AZURE_DEVOPS_WIKI: [
455
+ AzureDevOpsWikiTool.GET_WIKI,
456
+ AzureDevOpsWikiTool.GET_WIKI_PAGE_BY_PATH,
457
+ AzureDevOpsWikiTool.GET_WIKI_PAGE_BY_ID,
458
+ AzureDevOpsWikiTool.DELETE_PAGE_BY_PATH,
459
+ AzureDevOpsWikiTool.DELETE_PAGE_BY_ID,
460
+ AzureDevOpsWikiTool.MODIFY_WIKI_PAGE,
461
+ AzureDevOpsWikiTool.RENAME_WIKI_PAGE,
462
+ ],
463
+ Toolkit.AZURE_DEVOPS_WORK_ITEM: [
464
+ AzureDevOpsWorkItemTool.SEARCH_WORK_ITEMS,
465
+ AzureDevOpsWorkItemTool.CREATE_WORK_ITEM,
466
+ AzureDevOpsWorkItemTool.UPDATE_WORK_ITEM,
467
+ AzureDevOpsWorkItemTool.GET_WORK_ITEM,
468
+ AzureDevOpsWorkItemTool.LINK_WORK_ITEMS,
469
+ AzureDevOpsWorkItemTool.GET_RELATION_TYPES,
470
+ AzureDevOpsWorkItemTool.GET_COMMENTS,
471
+ ],
472
+ Toolkit.AZURE_DEVOPS_TEST_PLAN: [
473
+ AzureDevOpsTestPlanTool.CREATE_TEST_PLAN,
474
+ AzureDevOpsTestPlanTool.DELETE_TEST_PLAN,
475
+ AzureDevOpsTestPlanTool.GET_TEST_PLAN,
476
+ AzureDevOpsTestPlanTool.CREATE_TEST_SUITE,
477
+ AzureDevOpsTestPlanTool.DELETE_TEST_SUITE,
478
+ AzureDevOpsTestPlanTool.GET_TEST_SUITE,
479
+ AzureDevOpsTestPlanTool.ADD_TEST_CASE,
480
+ AzureDevOpsTestPlanTool.GET_TEST_CASE,
481
+ AzureDevOpsTestPlanTool.GET_TEST_CASES,
482
+ ],
483
+ Toolkit.ACCESS_MANAGEMENT: [
484
+ AccessManagementTool.KEYCLOAK,
485
+ ],
486
+ Toolkit.PROJECT_MANAGEMENT: [
487
+ ProjectManagementTool.GENERIC_JIRA,
488
+ ProjectManagementTool.GENERIC_CONFLUENCE,
489
+ ],
490
+ Toolkit.PLUGIN: [
491
+ PluginTool.PLUGIN,
492
+ ],
493
+ Toolkit.OPEN_API: [
494
+ OpenAPITool.INVOKE_EXTERNAL_API,
495
+ OpenAPITool.GET_OPEN_API_SPEC,
496
+ ],
497
+ Toolkit.NOTIFICATION: [
498
+ NotificationTool.EMAIL,
499
+ NotificationTool.TELEGRAM,
500
+ ],
501
+ Toolkit.DATA_MANAGEMENT: [
502
+ DataManagementTool.ELASTIC,
503
+ DataManagementTool.SQL,
504
+ ],
505
+ Toolkit.FILE_MANAGEMENT: [
506
+ FileManagementTool.READ_FILE,
507
+ FileManagementTool.WRITE_FILE,
508
+ FileManagementTool.LIST_DIRECTORY,
509
+ FileManagementTool.RUN_COMMAND_LINE,
510
+ FileManagementTool.CODE_INTERPRETER,
511
+ FileManagementTool.GENERATE_IMAGE_TOOL,
512
+ FileManagementTool.DIFF_UPDATE_FILE_TOOL,
513
+ FileManagementTool.STR_REPLACE_EDITOR,
514
+ ],
515
+ Toolkit.QUALITY_ASSURANCE: [
516
+ QualityAssuranceTool.ZEPHYR_SCALE,
517
+ QualityAssuranceTool.ZEPHYR_SQUAD,
518
+ ],
519
+ Toolkit.IT_SERVICE_MANAGEMENT: [
520
+ ITServiceManagementTool.SERVICENOW_TABLE_API,
521
+ ],
522
+ },
523
+ Section.EXTERNAL_TOOLS: {
524
+ ExternalToolKit.MCP_SERVERS: [
525
+ MCPServersTool.ADD_MCP_SERVER,
526
+ ]
527
+ },
528
+ }
@@ -21,7 +21,7 @@ WORK_ITEM_ID_PATTERN = r"workItems/(\d+)"
21
21
 
22
22
  vcs_integrations = {
23
23
  VcsTool.GITHUB: "github_integration",
24
- VcsTool.GITLAB: "gitlab_integration",
24
+ VcsTool.GITLAB: "git_integration",
25
25
  }
26
26
 
27
27
  project_management_integrations = {
@@ -0,0 +1,10 @@
1
+ from typing import Any, Dict
2
+
3
+ from codemie_test_harness.tests.utils.base_utils import BaseUtils
4
+
5
+
6
+ class WebhookUtils(BaseUtils):
7
+ """Utility class for webhook operations in CodeMie test harness."""
8
+
9
+ def trigger_webhook(self, webhook_id: str, data: Dict[str, Any] = None):
10
+ return self.client.webhook.trigger(webhook_id, data)
File without changes
@@ -0,0 +1,225 @@
1
+ """Webhook integration tests for CodeMie.
2
+
3
+ This module contains tests for webhook functionality including:
4
+ - Basic webhook operations with different resource types (assistant, workflow, datasource)
5
+ - Error handling and validation
6
+ - Webhook triggering verification
7
+ """
8
+
9
+ import pytest
10
+
11
+ from codemie_sdk.models.workflow import ExecutionStatus
12
+ from hamcrest import (
13
+ assert_that,
14
+ equal_to,
15
+ greater_than,
16
+ has_length,
17
+ has_item,
18
+ )
19
+ from codemie_test_harness.tests.utils.base_utils import get_random_name, wait_for_entity
20
+ from codemie_test_harness.tests.ui.test_data.datasource_test_data import (
21
+ DataSourceStatus,
22
+ )
23
+
24
+
25
+ @pytest.mark.webhook
26
+ @pytest.mark.api
27
+ class TestWebhookBasicOperations:
28
+ """Basic webhook operations tests - verify webhook creation and triggering for different resource types."""
29
+
30
+ def test_webhook_with_assistant(
31
+ self, assistant, webhook_integration, webhook_utils, conversation_utils
32
+ ):
33
+ """Test webhook can be created with assistant and triggers conversation creation."""
34
+ webhook_id = get_random_name()
35
+ message = f"Test message for {webhook_id}"
36
+
37
+ # Create assistant
38
+ assistant = assistant()
39
+
40
+ # Create webhook integration
41
+ webhook_integration(webhook_id, "assistant", assistant.id)
42
+
43
+ # Trigger webhook
44
+ response = webhook_utils.trigger_webhook(webhook_id, data=message)
45
+ assert_that(response.status_code, equal_to(200))
46
+ assert_that(
47
+ response.json()["message"], equal_to("Webhook invoked successfully")
48
+ )
49
+
50
+ # Wait for conversation
51
+ conversation = wait_for_entity(
52
+ lambda: conversation_utils.list_conversations(),
53
+ entity_name=f'"{message}"',
54
+ )
55
+
56
+ # Verify conversation details
57
+ assert_that(conversation.name.strip('"'), equal_to(message))
58
+ assert_that(conversation.initial_assistant_id, equal_to(assistant.id))
59
+ assert_that(conversation.assistant_ids, has_item(assistant.id))
60
+
61
+ def test_webhook_with_workflow(
62
+ self,
63
+ workflow_with_virtual_assistant,
64
+ default_llm,
65
+ webhook_integration,
66
+ webhook_utils,
67
+ workflow_utils,
68
+ ):
69
+ """Test webhook can be created with workflow and triggers workflow execution."""
70
+ webhook_id = get_random_name()
71
+ message = f"Test message for {webhook_id}"
72
+
73
+ # Create a simple workflow
74
+ workflow = workflow_with_virtual_assistant(webhook_id)
75
+
76
+ # Create webhook integration
77
+ webhook_integration(webhook_id, "workflow", workflow.id)
78
+
79
+ # Trigger webhook
80
+ response = webhook_utils.trigger_webhook(webhook_id, data=message)
81
+ assert_that(response.status_code, equal_to(200))
82
+ assert_that(
83
+ response.json()["message"], equal_to("Webhook invoked successfully")
84
+ )
85
+
86
+ # Verify workflow execution was created
87
+ executions = workflow_utils.get_executions(workflow)
88
+ assert_that(
89
+ executions,
90
+ has_length(greater_than(0)),
91
+ "Workflow execution should be created",
92
+ )
93
+
94
+ # Verify execution details
95
+ execution = executions[0]
96
+
97
+ assert_that(execution.prompt.strip('""'), equal_to(message))
98
+ assert_that(execution.workflow_id, equal_to(workflow.id))
99
+ assert_that(execution.status, equal_to(ExecutionStatus.IN_PROGRESS))
100
+
101
+ @pytest.mark.parametrize(
102
+ "datasource_fixture",
103
+ [
104
+ "jira_datasource",
105
+ "confluence_datasource",
106
+ "code_datasource",
107
+ ],
108
+ )
109
+ def test_webhook_with_datasource(
110
+ self,
111
+ request,
112
+ datasource_fixture,
113
+ webhook_integration,
114
+ webhook_utils,
115
+ datasource_utils,
116
+ ):
117
+ """Test webhook can be created with datasource and triggers successfully.
118
+
119
+ This test verifies webhook works with datasource as the resource type.
120
+ After triggering the webhook, it verifies that datasource indexing is in progress.
121
+
122
+ Test is parametrized to work with different datasource types:
123
+ - jira_datasource
124
+ - confluence_datasource
125
+ - code_datasource
126
+ """
127
+
128
+ # Get the datasource from the fixture
129
+ datasource = request.getfixturevalue(datasource_fixture)
130
+
131
+ # Create webhook integration with datasource
132
+ webhook_id = get_random_name()
133
+ webhook_integration(webhook_id, "datasource", datasource.id)
134
+
135
+ # Trigger webhook
136
+ response = webhook_utils.trigger_webhook(webhook_id)
137
+ assert_that(response.status_code, equal_to(200))
138
+ assert_that(
139
+ response.json()["message"], equal_to("Webhook invoked successfully")
140
+ )
141
+
142
+ # Verify datasource exists and check its status (indexing should be in progress)
143
+ triggered_datasource = datasource_utils.get_datasource(datasource.id)
144
+
145
+ assert_that(triggered_datasource.id, equal_to(datasource.id))
146
+ assert_that(triggered_datasource.name, equal_to(datasource.name))
147
+ assert_that(triggered_datasource.status, DataSourceStatus.FETCHING)
148
+
149
+
150
+ @pytest.mark.webhook
151
+ @pytest.mark.api
152
+ class TestWebhookErrorHandling:
153
+ """Tests for webhook error handling - invalid IDs and disabled webhooks."""
154
+
155
+ def test_webhook_trigger_with_invalid_id(self, webhook_utils):
156
+ """Test that triggering webhook with invalid ID returns error."""
157
+ invalid_webhook_id = "non_existent_webhook_" + get_random_name()
158
+
159
+ response = webhook_utils.trigger_webhook(invalid_webhook_id)
160
+
161
+ # Should return error status code
162
+ assert_that(response.status_code, equal_to(500))
163
+ assert_that(response.json()["detail"], equal_to("Webhook processing failed"))
164
+
165
+ def test_webhook_trigger_with_disabled_webhook(
166
+ self, assistant, webhook_integration, webhook_utils, conversation_utils
167
+ ):
168
+ """Test that disabled webhook cannot be triggered."""
169
+ assistant = assistant()
170
+ webhook_id = get_random_name()
171
+ message = f"Test message for {webhook_id}"
172
+
173
+ # Create webhook in disabled state
174
+ webhook_integration(webhook_id, "assistant", assistant.id, is_enabled=False)
175
+
176
+ # Try to trigger disabled webhook
177
+ response = webhook_utils.trigger_webhook(webhook_id, data=message)
178
+
179
+ # Should return error status code (not 200) for disabled webhook
180
+ assert_that(response.status_code, equal_to(500))
181
+ assert_that(response.json()["detail"], equal_to("Webhook processing failed"))
182
+
183
+ conversations = conversation_utils.get_conversation_by_assistant_id(
184
+ assistant.id
185
+ )
186
+ assert_that(len(conversations), equal_to(0))
187
+
188
+ def test_webhook_invalid_resource_id(self, webhook_integration, webhook_utils):
189
+ """Test webhook with invalid resource ID."""
190
+ webhook_id = get_random_name()
191
+ message = f"Test message for {webhook_id}"
192
+ invalid_resource_id = "invalid_resource_" + get_random_name()
193
+
194
+ # Create webhook with invalid resource ID
195
+ webhook_integration(webhook_id, "assistant", invalid_resource_id)
196
+
197
+ # Trigger webhook - should handle gracefully
198
+ response = webhook_utils.trigger_webhook(webhook_id, data=message)
199
+
200
+ assert_that(response.status_code, equal_to(500))
201
+ assert_that(response.json()["detail"], equal_to("Webhook processing failed"))
202
+
203
+ def test_webhook_with_file_datasource(
204
+ self,
205
+ request,
206
+ file_datasource,
207
+ webhook_integration,
208
+ webhook_utils,
209
+ datasource_utils,
210
+ ):
211
+ """Test webhook with unsupported datasource type."""
212
+
213
+ # Create webhook integration with datasource
214
+ webhook_id = get_random_name()
215
+ webhook_integration(webhook_id, "datasource", file_datasource.id)
216
+
217
+ # Trigger webhook
218
+ response = webhook_utils.trigger_webhook(webhook_id)
219
+ assert_that(response.status_code, equal_to(403))
220
+ assert_that(
221
+ response.json()["detail"],
222
+ equal_to(
223
+ "Datasource type 'knowledge_base_file' is not supported via webhook."
224
+ ),
225
+ )