Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manage Whatsapp Flows #1224

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

maheshsattala
Copy link
Contributor

@maheshsattala maheshsattala commented Jun 4, 2024

  1. Added CRUD Operations for the Whatsapp flow
  2. Modified Add and Update Whatsapp flows APIs.
  3. Added and fixed related test cases both unit and integration test cases.

Summary by CodeRabbit

  • New Features

    • Introduced comprehensive WhatsApp flow management, including adding, editing, previewing, retrieving, deleting, deprecating, and publishing flows.
    • Added structured JSON format for defining feedback screens in WhatsApp flows.
  • Tests

    • Added extensive test coverage for WhatsApp flow operations, including error scenarios and successful execution.
  • Bug Fixes

    • Enhanced validation and error handling for WhatsApp flow requests.

2. Modified Add and Update Whatsapp flows APIs.
3. Added and fixed related test cases both unit and integration test cases.
Copy link

coderabbitai bot commented Jun 4, 2024

Walkthrough

The recent updates introduce comprehensive WhatsApp flow management capabilities to the Kairon API. New endpoints have been added for creating, editing, previewing, retrieving, deprecating, deleting, and publishing WhatsApp flows. These functionalities are supported by backend changes, including new methods in the dialog360.py file, updated constants, and utility functions. Extensive testing has also been implemented to ensure robust functionality.

Changes

Files/Modules Change Summary
kairon/api/app/routers/bot/channels.py Added endpoints for managing WhatsApp flows: add, edit, preview, retrieve, deprecate, delete, publish, and get assets.
kairon/shared/channels/whatsapp/bsp/dialog360.py Introduced new methods for WhatsApp flow operations: add, edit, preview, retrieve, deprecate, delete, publish, and get assets.
kairon/shared/constants.py Added new enums for flow management and updated existing enums.
kairon/shared/utils.py Added a method for validating flow requests and modified HTTP request execution for file uploads.
metadata/flows/flow_json.json Introduced a structured JSON format for defining feedback screens in a flow.
tests/integration_test/services_test.py Added and modified test functions for various WhatsApp flow operations, including error handling.
tests/testing_data/flow/sample_flow.json Defined a sample flow with screens for personal details and feedback collection.
tests/unit_test/channels/bsp_test.py Added test methods for WhatsApp flow operations, covering various scenarios and error handling.

Sequence Diagram(s) (Beta)

sequenceDiagram
    participant User
    participant API
    participant BSPFactory
    participant Dialog360

    User->>API: POST /add_whatsapp_flow
    API->>BSPFactory: Create instance
    BSPFactory->>Dialog360: add_whatsapp_flow(request_data)
    Dialog360-->>BSPFactory: Flow added response
    BSPFactory-->>API: Flow added response
    API-->>User: Flow added response
Loading
sequenceDiagram
    participant User
    participant API
    participant BSPFactory
    participant Dialog360

    User->>API: GET /preview_whatsapp_flow
    API->>BSPFactory: Create instance
    BSPFactory->>Dialog360: preview_whatsapp_flow(flow_id)
    Dialog360-->>BSPFactory: Flow preview data
    BSPFactory-->>API: Flow preview data
    API-->>User: Flow preview data
Loading

Poem

In the world of code so bright,
WhatsApp flows now take flight.
Add, edit, preview with ease,
Kairon’s updates sure to please.
Test and validate, all in line,
Flows now sparkle, simply divine.
🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Outside diff range and nitpick comments (3)
tests/unit_test/channels/bsp_test.py (1)

Line range hint 19-19: Remove unused import of mongomock.MongoClient.

- from mongomock import MongoClient
Tools
Ruff

615-615: Local variable flow_id is assigned to but never used


624-624: Local variable flow_id is assigned to but never used


644-644: Local variable flow_id is assigned to but never used


673-673: Local variable flow_id is assigned to but never used

kairon/shared/utils.py (1)

Line range hint 992-992: Unused local variable e.

The variable e in the execute_http_request method is assigned but never used. Consider removing it or using it as needed.

-        except Exception as e:
+        except Exception:
tests/integration_test/services_test.py (1)

19012-19029: Consider adding more detailed assertions to verify the structure and content of the error responses.

Adding assertions to check specific fields in the error response can help ensure that the API is returning all expected information correctly.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 86569dd and 61523c8.

Files selected for processing (9)
  • kairon/api/app/routers/bot/channels.py (1 hunks)
  • kairon/shared/channels/whatsapp/bsp/dialog360.py (2 hunks)
  • kairon/shared/constants.py (2 hunks)
  • kairon/shared/utils.py (3 hunks)
  • metadata/flows/default_meta_flows.json (1 hunks)
  • metadata/flows/flow_json.json (1 hunks)
  • tests/integration_test/services_test.py (2 hunks)
  • tests/testing_data/flow/sample_flow.json (1 hunks)
  • tests/unit_test/channels/bsp_test.py (2 hunks)
Files not summarized due to errors (1)
  • metadata/flows/default_meta_flows.json: Error: Message exceeds token limit
Files skipped from review due to trivial changes (2)
  • metadata/flows/flow_json.json
  • tests/testing_data/flow/sample_flow.json
Additional context used
Ruff
tests/unit_test/channels/bsp_test.py

19-19: mongomock.MongoClient imported but unused


615-615: Local variable flow_id is assigned to but never used


624-624: Local variable flow_id is assigned to but never used


644-644: Local variable flow_id is assigned to but never used


673-673: Local variable flow_id is assigned to but never used


1007-1007: Local variable partner_id is assigned to but never used


1008-1008: Local variable channel_id is assigned to but never used


1152-1152: Local variable partner_id is assigned to but never used


1153-1153: Local variable account_id is assigned to but never used


1215-1215: Local variable partner_id is assigned to but never used


1216-1216: Local variable account_id is assigned to but never used

kairon/shared/utils.py

992-992: Local variable e is assigned to but never used

tests/integration_test/services_test.py

835-835: f-string without any placeholders


845-845: f-string without any placeholders


2460-2460: Local variable response_three is assigned to but never used


2684-2684: Comparison to None should be cond is None


5509-5509: Avoid equality comparisons to True; use if actual["success"]: for truth checks


5718-5718: Do not compare types, use isinstance()


8543-8543: f-string without any placeholders


9083-9083: Local variable response_one is assigned to but never used


9087-9087: Local variable response_two is assigned to but never used


9091-9091: Local variable response_three is assigned to but never used


9114-9114: f-string without any placeholders


9257-9257: f-string without any placeholders


9737-9737: Local variable response_delete_story_one is assigned to but never used


9742-9742: Local variable response_delete_story_two is assigned to but never used


10430-10430: Local variable payload_response is assigned to but never used


12528-12528: f-string without any placeholders


14048-14048: Comparison to None should be cond is None


14094-14094: Comparison to None should be cond is None


16911-16911: f-string without any placeholders


16922-16922: f-string without any placeholders


16933-16933: f-string without any placeholders


16946-16946: f-string without any placeholders


16956-16956: f-string without any placeholders


16965-16965: f-string without any placeholders


16982-16982: f-string without any placeholders


16988-16988: f-string without any placeholders


16994-16994: f-string without any placeholders


17014-17014: f-string without any placeholders


17018-17018: f-string without any placeholders


17024-17024: f-string without any placeholders


17035-17035: f-string without any placeholders


17052-17052: f-string without any placeholders


17065-17065: f-string without any placeholders


17078-17078: f-string without any placeholders


17092-17092: f-string without any placeholders


17124-17124: f-string without any placeholders


18943-18943: Comparison to None should be cond is None


18984-18984: Comparison to None should be cond is None


18998-18998: Comparison to None should be cond is None


19525-19525: Local variable data is assigned to but never used


19550-19550: Local variable data is assigned to but never used


19578-19578: Local variable data is assigned to but never used


19597-19597: Local variable data is assigned to but never used


19616-19616: Local variable data is assigned to but never used


19645-19645: Local variable data is assigned to but never used


19845-19845: f-string without any placeholders


21142-21142: Local variable mock is assigned to but never used


22499-22499: f-string without any placeholders


22534-22534: Comparison to None should be cond is None


22623-22623: Comparison to None should be cond is None


22649-22649: Comparison to None should be cond is None


22889-22889: Avoid equality comparisons to False; use if not actual["data"]["logs"][1]["translate_responses"]: for false checks


22890-22890: Avoid equality comparisons to False; use if not actual["data"]["logs"][1]["translate_actions"]: for false checks


22906-22906: f-string without any placeholders


23152-23152: f-string without any placeholders


23204-23204: f-string without any placeholders


23862-23862: f-string without any placeholders


23876-23876: f-string without any placeholders


23969-23969: Local variable passwrd_change_response is assigned to but never used


24049-24049: Local variable regsiter_response is assigned to but never used


24081-24081: Local variable regsiter_response is assigned to but never used


24286-24286: Avoid equality comparisons to False; use if not actual["success"]: for false checks


24290-24290: f-string without any placeholders

Additional comments not posted (54)
kairon/shared/constants.py (2)

65-65: Added new enum value for flow_creation under UserActivityType.

This addition aligns with the new functionalities introduced for managing WhatsApp flows, ensuring that user activities related to flow creation are properly logged.


135-154: Introduced new enums FlowCategories and FlowTemplates.

These enums are essential for categorizing and templating the new WhatsApp flows. This structured approach enhances maintainability and scalability of flow management.

kairon/api/app/routers/bot/channels.py (8)

109-121: Added new endpoint for adding WhatsApp flows.

This endpoint correctly implements the functionality to add new WhatsApp flows as drafts, which is crucial for the dynamic management of flows in a business service provider context.


124-137: Added new endpoint for editing WhatsApp flows.

This endpoint provides the functionality to edit existing WhatsApp flows, which is necessary for maintaining and updating the flows as per business requirements.


140-152: Added new endpoint for previewing WhatsApp flows.

This endpoint facilitates the previewing of WhatsApp flows, allowing users to review changes before they are finalized, which enhances the user experience and reduces errors.


155-167: Added new endpoint for retrieving WhatsApp flow assets.

This endpoint is well-implemented to fetch all assets related to a specific flow, supporting richer content management within flows.


170-182: Added new endpoint for deprecating WhatsApp flows.

This functionality is crucial for managing the lifecycle of WhatsApp flows, allowing for the deprecation of outdated or irrelevant flows.


185-198: Added new endpoint for retrieving all WhatsApp flows.

This endpoint effectively retrieves all WhatsApp flows, with support for filtering, which is essential for managing a large number of flows.


201-213: Added new endpoint for deleting WhatsApp flows.

Properly implemented functionality for deleting WhatsApp flows, which is necessary for effective flow management and cleanup.


216-228: Added new endpoint for publishing WhatsApp flows.

This endpoint enables the publishing of WhatsApp flows, transitioning them from draft to active status, which is a critical step in the flow management process.

kairon/shared/channels/whatsapp/bsp/dialog360.py (11)

86-93: Added method get_flow_endpoint_url to construct the URL for flow operations.

This method is crucial for encapsulating the construction of URLs used in various flow operations, promoting code reuse and maintainability.


95-112: Added method add_whatsapp_flow to handle the addition of new WhatsApp flows.

This method correctly implements the addition of new flows, including validation and logging, which are essential for robust flow management.


117-126: Added method get_flow_json_from_template to fetch flow JSON based on a template.

This method enhances the flexibility of flow creation by allowing flows to be initialized from templates, which can streamline the flow setup process.


128-131: Added method write_flow_json_into_file to save flow JSON to a file.

This utility method is essential for persisting flow configurations, which is important for auditability and version control of flow definitions.


133-152: Added method edit_whatsapp_flow to handle the editing of existing WhatsApp flows.

This method is well-implemented to support the editing of flows, including handling file uploads, which is crucial for managing complex flow configurations.


160-167: Added method preview_whatsapp_flow to fetch a preview of a WhatsApp flow.

This method provides a crucial functionality for previewing flows, which can help in quality assurance and user acceptance testing before flows go live.


172-179: Added method get_whatsapp_flow_assets to retrieve assets for a specific flow.

This method effectively fetches assets associated with a flow, supporting enhanced content management within the flow.


184-191: Added method deprecate_whatsapp_flow to mark a flow as deprecated.

This method is essential for lifecycle management of flows, allowing outdated or irrelevant flows to be marked accordingly.


196-205: Added method list_whatsapp_flows to retrieve all flows with optional fields.

This method provides comprehensive functionality to list all flows, with support for field-based filtering, which is useful for managing a large number of flows.


210-217: Added method delete_flow to remove a specific WhatsApp flow.

This method correctly implements the deletion of flows, which is necessary for effective flow management and cleanup.


222-229: Added method publish_flow to make a WhatsApp flow active.

This method enables the transition of a flow from draft to active status, which is a critical functionality for making flows available to end-users.

tests/unit_test/channels/bsp_test.py (28)

294-304: Ensure proper error handling for missing keys in the request body.


305-315: Validate categories properly to avoid runtime errors.


316-326: Check for valid templates to prevent incorrect flow creation.


327-337: Handle the scenario where the channel is not found more gracefully.


338-359: Improve error handling when adding a WhatsApp flow fails.


360-396: Ensure that the successful addition of a WhatsApp flow is handled correctly.


397-405: Handle the scenario where the channel is not found during flow editing.


406-426: Improve error handling when editing a WhatsApp flow fails.


427-451: Ensure that the successful editing of a WhatsApp flow is handled correctly.


452-459: Handle the scenario where the channel is not found during asset retrieval.


460-479: Improve error handling when retrieving WhatsApp flow assets fails.


480-509: Ensure that the successful retrieval of WhatsApp flow assets is handled correctly.


510-517: Handle the scenario where the channel is not found during flow deprecation.


518-537: Improve error handling when deprecating a WhatsApp flow fails.


538-557: Ensure that the successful deprecation of a WhatsApp flow is handled correctly.


558-565: Handle the scenario where the channel is not found during flow preview.


566-585: Improve error handling when previewing a WhatsApp flow fails.


586-611: Ensure that the successful preview of a WhatsApp flow is handled correctly.


612-619: Handle the scenario where the channel is not found during flow listing.

Tools
Ruff

615-615: Local variable flow_id is assigned to but never used


620-639: Improve error handling when listing WhatsApp flows fails.

Tools
Ruff

624-624: Local variable flow_id is assigned to but never used


640-668: Ensure that the successful listing of WhatsApp flows with query parameters is handled correctly.

Tools
Ruff

644-644: Local variable flow_id is assigned to but never used


669-709: Ensure that the successful listing of WhatsApp flows is handled correctly.

Tools
Ruff

673-673: Local variable flow_id is assigned to but never used


710-717: Handle the scenario where the channel is not found during flow deletion.


718-737: Improve error handling when deleting a WhatsApp flow fails.


738-757: Ensure that the successful deletion of a WhatsApp flow is handled correctly.


758-765: Handle the scenario where the channel is not found during flow publication.


766-785: Improve error handling when publishing a WhatsApp flow fails.


786-805: Ensure that the successful publication of a WhatsApp flow is handled correctly.

metadata/flows/default_meta_flows.json (4)

3-106: The JSON structure for WhatsApp flow categories and templates is well-formed and aligns with the new features described in the PR.


3-37: The categories defined in the JSON match the new FlowCategories enum additions and are correctly structured.


38-105: All templates have valid JSON strings for flow_json and the is_endpoint_configured flags are used appropriately.


38-105: All templates necessary for the new WhatsApp flow functionalities are present and correctly defined.

tests/integration_test/services_test.py (1)

19012-19029: Ensure consistent error handling across tests.

Verification successful

The verification script has confirmed that the error handling in the tests is consistent, with multiple instances of assertions checking for the error code 422.

  • The pattern assert actual["error_code"] == 422 is used consistently across the test file.
  • This indicates that the error handling follows a uniform pattern.
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that all error handling in tests is consistent and follows the same pattern.

# Test: Search for error handling patterns in tests. Expect: Consistent usage of assertions for error codes and messages.
rg --type python $'assert.*"error_code".*422' tests/integration_test/services_test.py

Length of output: 117



Script:

#!/bin/bash
# Description: Verify that all error handling in tests is consistent and follows the same pattern.

# Test: Search for error handling patterns in tests. Expect: Consistent usage of assertions for error codes and messages.
rg --type py $'assert.*"error_code".*422' tests/integration_test/services_test.py

Length of output: 13237

Comment on lines +19012 to +19029
@patch("kairon.shared.channels.whatsapp.bsp.dialog360.BSP360Dialog.get_partner_auth_token", autospec=True)
def test_add_whatsapp_flow_error(mock_get_partner_auth_token):
mock_get_partner_auth_token.return_value = "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs.ImtpZCI6Ik1EZEZOVFk1UVVVMU9FSXhPRGN3UVVZME9EUTFRVFJDT1.RSRU9VUTVNVGhDTURWRk9UUTNPQSJ9"
data = {
"name": "flow with multiple categories",
"categories": ["APPOINTMENT_BOOKING", "OTHER", "SURVEY"],
"template": "FLOWS_OFFSITE_CALL_TO_ACTION",
}
response = client.post(
f"/api/bot/{pytest.bot}/channels/whatsapp/flows/360dialog",
json={'data': data},
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)
actual = response.json()
assert not actual["success"]
assert actual["error_code"] == 422
assert actual["message"] == "Channel not found!"
assert actual["data"] is None
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor repeated mock setup code to a shared fixture or helper function.

The repeated setup code for mock_get_partner_auth_token can be refactored into a pytest fixture or a helper function to reduce duplication and improve maintainability.

Comment on lines +19478 to +19660
"name": "my first flow"
}
]
mock_list_whatsapp_flows.return_value = api_response

response = client.get(
f"/api/bot/{pytest.bot}/channels/whatsapp/flows/360dialog",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)
actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["data"]['flows'] == api_response


@patch("kairon.shared.channels.whatsapp.bsp.dialog360.BSP360Dialog.delete_flow", autospec=True)
def test_delete_whatsapp_flow(mock_delete_flow):
data = {
"name": "flow with multiple categories",
"categories": ["APPOINTMENT_BOOKING", "OTHER", "SURVEY"]
}
api_response = {"success": True}
mock_delete_flow.return_value = api_response

response = client.delete(
f"/api/bot/{pytest.bot}/channels/whatsapp/flows/360dialog/test_flow_id",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)
actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["data"] == api_response


@patch("kairon.shared.channels.whatsapp.bsp.dialog360.BSP360Dialog.publish_flow", autospec=True)
def test_publish_whatsapp_flow(mock_publish_flow):
data = {
"name": "flow with multiple categories",
"categories": ["APPOINTMENT_BOOKING", "OTHER", "SURVEY"]
}
api_response = {"success": True}
mock_publish_flow.return_value = api_response

response = client.post(
f"/api/bot/{pytest.bot}/channels/whatsapp/flows/360dialog/test_flow_id/publish",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)
actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["data"] == api_response


@patch("kairon.shared.channels.whatsapp.bsp.dialog360.BSP360Dialog.get_whatsapp_flow_assets", autospec=True)
def test_get_whatsapp_flow_assets(mock_get_whatsapp_flow_assets):
data = {
"name": "flow with multiple categories",
"categories": ["APPOINTMENT_BOOKING", "OTHER", "SURVEY"]
}
api_response = {
"assets": [
{
"asset_type": "FLOW_JSON",
"download_url": "https://mmg.whatsapp.net/m1/v/t24/An8n-Ot0L5sxj8lupzxfUTfHYhsdsdsdsRyqAZRySBcATvtUGgPjP76UJKS0wMopyj6SNTmNmf_F1pLAt04wbP3B9kFCIpvy7oOG6CM3HK4wFY61Z7TiLDxjGvzEgXjdog6A?ccb=10-5&oh=01_AdTq_Njj-foFgD0-KlMXq4AbdhrqLoNm6_CtlsxZxC03rA&oe=65F414CD&_nc_sid=471a72",
"name": "flow.json"
}
],
"count": 1,
"total": 1
}
mock_get_whatsapp_flow_assets.return_value = api_response

response = client.get(
f"/api/bot/{pytest.bot}/channels/whatsapp/flows/360dialog/test_flow_id/assets",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)
actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["data"] == api_response


@patch("kairon.shared.channels.whatsapp.bsp.dialog360.BSP360Dialog.deprecate_whatsapp_flow", autospec=True)
def test_deprecate_whatsapp_flow(mock_deprecate_whatsapp_flow):
data = {
"name": "flow with multiple categories",
"categories": ["APPOINTMENT_BOOKING", "OTHER", "SURVEY"]
}
api_response = {"success": True}
mock_deprecate_whatsapp_flow.return_value = api_response

response = client.post(
f"/api/bot/{pytest.bot}/channels/whatsapp/flows/360dialog/test_flow_id/deprecate",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)
actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["data"] == api_response

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimize test setup by reusing data structures.

Many tests are setting up similar data structures. Consider using a shared fixture or helper function to define these data structures, reducing redundancy and making the tests easier to maintain.

Tools
Ruff

19525-19525: Local variable data is assigned to but never used


19550-19550: Local variable data is assigned to but never used


19578-19578: Local variable data is assigned to but never used


19597-19597: Local variable data is assigned to but never used


19616-19616: Local variable data is assigned to but never used


19645-19645: Local variable data is assigned to but never used


@patch("kairon.shared.channels.whatsapp.bsp.dialog360.BSP360Dialog.preview_whatsapp_flow", autospec=True)
def test_preview_whatsapp_flow(mock_preview_whatsapp_flow):
data = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove unused local variables as indicated by static analysis.

- data = {
-     "name": "flow with multiple categories",
-     "categories": ["APPOINTMENT_BOOKING", "OTHER", "SURVEY"]
- }

These data variables are defined but never used in the respective test functions, leading to unnecessary code clutter.

Also applies to: 19550-19550, 19578-19578, 19597-19597, 19616-19616, 19645-19645

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
data = {
Tools
Ruff

19525-19525: Local variable data is assigned to but never used

Comment on lines +1304 to +1317
def validate_add_flow_request(data: Dict):
required_keys = ['name', 'categories', 'template']
missing_keys = [key for key in required_keys if key not in data]
if missing_keys:
raise AppException(f'Missing {", ".join(missing_keys)} in request body!')
categories = data.get('categories')
template = data.get('template')
invalid_categories = [category for category in categories
if category not in [flow_category.value for flow_category in FlowCategories]]
invalid_template = template if template not in [flow_template.value for flow_template in FlowTemplates] else ""
if invalid_categories:
raise AppException(f'Invalid categories {", ".join(invalid_categories)} in request body!')
if invalid_template:
raise AppException(f'Invalid template {template} in request body!')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure proper validation of categories and template in validate_add_flow_request.

The method validate_add_flow_request checks for missing keys, invalid categories, and templates. However, it does not handle cases where categories or template might be empty or have incorrect types. Consider adding checks to ensure these fields are not empty and are of the expected type.

+        if not categories or not isinstance(categories, list):
+            raise AppException('Categories must be a non-empty list!')
+        if not template or not isinstance(template, str):
+            raise AppException('Template must be a non-empty string!')
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
def validate_add_flow_request(data: Dict):
required_keys = ['name', 'categories', 'template']
missing_keys = [key for key in required_keys if key not in data]
if missing_keys:
raise AppException(f'Missing {", ".join(missing_keys)} in request body!')
categories = data.get('categories')
template = data.get('template')
invalid_categories = [category for category in categories
if category not in [flow_category.value for flow_category in FlowCategories]]
invalid_template = template if template not in [flow_template.value for flow_template in FlowTemplates] else ""
if invalid_categories:
raise AppException(f'Invalid categories {", ".join(invalid_categories)} in request body!')
if invalid_template:
raise AppException(f'Invalid template {template} in request body!')
def validate_add_flow_request(data: Dict):
required_keys = ['name', 'categories', 'template']
missing_keys = [key for key in required_keys if key not in data]
if missing_keys:
raise AppException(f'Missing {", ".join(missing_keys)} in request body!')
categories = data.get('categories')
template = data.get('template')
if not categories or not isinstance(categories, list):
raise AppException('Categories must be a non-empty list!')
if not template or not isinstance(template, str):
raise AppException('Template must be a non-empty string!')
invalid_categories = [category for category in categories
if category not in [flow_category.value for flow_category in FlowCategories]]
invalid_template = template if template not in [flow_template.value for flow_template in FlowTemplates] else ""
if invalid_categories:
raise AppException(f'Invalid categories {", ".join(invalid_categories)} in request body!')
if invalid_template:
raise AppException(f'Invalid template {template} in request body!')

Comment on lines +1714 to +1723
if kwargs.get('files'):
response = session.request(
request_method.upper(), http_url, data=request_body, headers=headers,
timeout=kwargs.get('timeout'), files=kwargs.get('files')
)
else:
response = session.request(
request_method.upper(), http_url, json=request_body, headers=headers,
timeout=kwargs.get('timeout')
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle file uploads in HTTP requests more robustly.

The method execute_http_request handles file uploads but does not check if the files parameter is of the correct type. This could lead to errors if an incorrect type is passed. Consider adding a type check for the files parameter.

+        if kwargs.get('files') and not isinstance(kwargs.get('files'), dict):
+            raise AppException('Files must be provided as a dictionary!')
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
if kwargs.get('files'):
response = session.request(
request_method.upper(), http_url, data=request_body, headers=headers,
timeout=kwargs.get('timeout'), files=kwargs.get('files')
)
else:
response = session.request(
request_method.upper(), http_url, json=request_body, headers=headers,
timeout=kwargs.get('timeout')
)
if kwargs.get('files'):
if not isinstance(kwargs.get('files'), dict):
raise AppException('Files must be provided as a dictionary!')
response = session.request(
request_method.upper(), http_url, data=request_body, headers=headers,
timeout=kwargs.get('timeout'), files=kwargs.get('files')
)
else:
response = session.request(
request_method.upper(), http_url, json=request_body, headers=headers,
timeout=kwargs.get('timeout')
)

@hiteshghuge hiteshghuge self-assigned this Jun 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants