Преглед изворни кода

Test: Add dialog app test suite and update common.py with dialog endpoints (#8729)

### What problem does this PR solve?

This commit introduces a comprehensive test suite for the dialog app,
including tests for creating, updating, retrieving, listing, and
deleting dialogs. Additionally, the common.py file has been updated to
include necessary API endpoints and helper functions for dialog
operations.

### Type of change

- [x] Add test cases
tags/v0.20.0
Liu An пре 3 месеци
родитељ
комит
2a03d49a84
No account linked to committer's email address

+ 58
- 1
test/testcases/test_web_api/common.py Прегледај датотеку

@@ -25,7 +25,7 @@ HEADERS = {"Content-Type": "application/json"}
KB_APP_URL = f"/{VERSION}/kb"
DOCUMENT_APP_URL = f"/{VERSION}/document"
CHUNK_API_URL = f"/{VERSION}/chunk"
# CHAT_ASSISTANT_API_URL = "/api/v1/chats"
DIALOG_APP_URL = f"/{VERSION}/dialog"
# SESSION_WITH_CHAT_ASSISTANT_API_URL = "/api/v1/chats/{chat_id}/sessions"
# SESSION_WITH_AGENT_API_URL = "/api/v1/agents/{agent_id}/sessions"

@@ -201,3 +201,60 @@ def batch_add_chunks(auth, doc_id, num):
res = add_chunk(auth, {"doc_id": doc_id, "content_with_weight": f"chunk test {i}"})
chunk_ids.append(res["data"]["chunk_id"])
return chunk_ids


# DIALOG APP
def create_dialog(auth, payload=None, *, headers=HEADERS, data=None):
res = requests.post(url=f"{HOST_ADDRESS}{DIALOG_APP_URL}/set", headers=headers, auth=auth, json=payload, data=data)
return res.json()


def update_dialog(auth, payload=None, *, headers=HEADERS, data=None):
res = requests.post(url=f"{HOST_ADDRESS}{DIALOG_APP_URL}/set", headers=headers, auth=auth, json=payload, data=data)
return res.json()


def get_dialog(auth, params=None, *, headers=HEADERS):
res = requests.get(url=f"{HOST_ADDRESS}{DIALOG_APP_URL}/get", headers=headers, auth=auth, params=params)
return res.json()


def list_dialogs(auth, *, headers=HEADERS):
res = requests.get(url=f"{HOST_ADDRESS}{DIALOG_APP_URL}/list", headers=headers, auth=auth)
return res.json()


def delete_dialog(auth, payload=None, *, headers=HEADERS, data=None):
res = requests.post(url=f"{HOST_ADDRESS}{DIALOG_APP_URL}/rm", headers=headers, auth=auth, json=payload, data=data)
return res.json()


def batch_create_dialogs(auth, num, kb_ids=None):
if kb_ids is None:
kb_ids = []

dialog_ids = []
for i in range(num):
payload = {
"name": f"dialog_{i}",
"description": f"Test dialog {i}",
"kb_ids": kb_ids,
"prompt_config": {"system": "You are a helpful assistant. Use the following knowledge to answer questions: {knowledge}", "parameters": [{"key": "knowledge", "optional": False}]},
"top_n": 6,
"top_k": 1024,
"similarity_threshold": 0.1,
"vector_similarity_weight": 0.3,
"llm_setting": {"model": "gpt-3.5-turbo", "temperature": 0.7},
}
res = create_dialog(auth, payload)
if res["code"] == 0:
dialog_ids.append(res["data"]["id"])
return dialog_ids


def delete_dialogs(auth):
res = list_dialogs(auth)
if res["code"] == 0 and res["data"]:
dialog_ids = [dialog["id"] for dialog in res["data"]]
if dialog_ids:
delete_dialog(auth, {"dialog_ids": dialog_ids})

+ 9
- 0
test/testcases/test_web_api/conftest.py Прегледај датотеку

@@ -21,6 +21,7 @@ from common import (
batch_create_datasets,
bulk_upload_documents,
delete_chunks,
delete_dialogs,
list_chunks,
list_documents,
list_kbs,
@@ -97,6 +98,14 @@ def clear_datasets(request: FixtureRequest, WebApiAuth: RAGFlowWebApiAuth):
request.addfinalizer(cleanup)


@pytest.fixture(scope="function")
def clear_dialogs(request, WebApiAuth):
def cleanup():
delete_dialogs(WebApiAuth)

request.addfinalizer(cleanup)


@pytest.fixture(scope="class")
def add_dataset(request: FixtureRequest, WebApiAuth: RAGFlowWebApiAuth) -> str:
def cleanup():

+ 50
- 0
test/testcases/test_web_api/test_dialog_app/conftest.py Прегледај датотеку

@@ -0,0 +1,50 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
from common import batch_create_dialogs, delete_dialogs


@pytest.fixture(scope="function")
def add_dialog_func(request, WebApiAuth, add_dataset_func):
def cleanup():
delete_dialogs(WebApiAuth)

request.addfinalizer(cleanup)

dataset_id = add_dataset_func
return dataset_id, batch_create_dialogs(WebApiAuth, 1, [dataset_id])[0]


@pytest.fixture(scope="class")
def add_dialogs(request, WebApiAuth, add_dataset):
def cleanup():
delete_dialogs(WebApiAuth)

request.addfinalizer(cleanup)

dataset_id = add_dataset
return dataset_id, batch_create_dialogs(WebApiAuth, 5, [dataset_id])


@pytest.fixture(scope="function")
def add_dialogs_func(request, WebApiAuth, add_dataset_func):
def cleanup():
delete_dialogs(WebApiAuth)

request.addfinalizer(cleanup)

dataset_id = add_dataset_func
return dataset_id, batch_create_dialogs(WebApiAuth, 5, [dataset_id])

+ 170
- 0
test/testcases/test_web_api/test_dialog_app/test_create_dialog.py Прегледај датотеку

@@ -0,0 +1,170 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from concurrent.futures import ThreadPoolExecutor, as_completed

import pytest
from common import create_dialog
from configs import CHAT_ASSISTANT_NAME_LIMIT, INVALID_API_TOKEN
from hypothesis import example, given, settings
from libs.auth import RAGFlowWebApiAuth
from utils.hypothesis_utils import valid_names


@pytest.mark.usefixtures("clear_dialogs")
class TestAuthorization:
@pytest.mark.p1
@pytest.mark.parametrize(
"invalid_auth, expected_code, expected_message",
[
(None, 401, "<Unauthorized '401: Unauthorized'>"),
(RAGFlowWebApiAuth(INVALID_API_TOKEN), 401, "<Unauthorized '401: Unauthorized'>"),
],
ids=["empty_auth", "invalid_api_token"],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message):
payload = {"name": "auth_test", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = create_dialog(invalid_auth, payload)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res


@pytest.mark.usefixtures("clear_dialogs")
class TestCapability:
@pytest.mark.p3
def test_create_dialog_100(self, WebApiAuth):
for i in range(100):
payload = {"name": f"dialog_{i}", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, f"Failed to create dialog {i}"

@pytest.mark.p3
def test_create_dialog_concurrent(self, WebApiAuth):
count = 100
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(create_dialog, WebApiAuth, {"name": f"dialog_{i}", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}) for i in range(count)]
responses = list(as_completed(futures))
assert len(responses) == count, responses
assert all(future.result()["code"] == 0 for future in futures)


@pytest.mark.usefixtures("clear_dialogs")
class TestDialogCreate:
@pytest.mark.p1
@given(name=valid_names())
@example("a" * CHAT_ASSISTANT_NAME_LIMIT)
@settings(max_examples=20)
def test_name(self, WebApiAuth, name):
payload = {"name": name, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p2
@pytest.mark.parametrize(
"name, expected_code, expected_message",
[
("", 102, "Dialog name can't be empty."),
(" ", 102, "Dialog name can't be empty."),
("a" * (CHAT_ASSISTANT_NAME_LIMIT + 1), 102, "Dialog name length is 256 which is larger than 255"),
(0, 102, "Dialog name must be string."),
(None, 102, "Dialog name must be string."),
],
ids=["empty_name", "space_name", "too_long_name", "invalid_name", "None_name"],
)
def test_name_invalid(self, WebApiAuth, name, expected_code, expected_message):
payload = {"name": name, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res

@pytest.mark.p1
def test_prompt_config_required(self, WebApiAuth):
payload = {"name": "test_dialog"}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 101, res
assert res["message"] == "required argument are missing: prompt_config; ", res

@pytest.mark.p1
def test_prompt_config_with_knowledge_no_kb(self, WebApiAuth):
payload = {"name": "test_dialog", "prompt_config": {"system": "You are a helpful assistant. Use this knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 102, res
assert "Please remove `{knowledge}` in system prompt" in res["message"], res

@pytest.mark.p1
def test_prompt_config_parameter_not_used(self, WebApiAuth):
payload = {"name": "test_dialog", "prompt_config": {"system": "You are a helpful assistant.", "parameters": [{"key": "unused_param", "optional": False}]}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 102, res
assert "Parameter 'unused_param' is not used" in res["message"], res

@pytest.mark.p1
def test_create_with_kb_ids(self, WebApiAuth, add_dataset_func):
dataset_id = add_dataset_func
payload = {
"name": "test_dialog_with_kb",
"kb_ids": [dataset_id],
"prompt_config": {"system": "You are a helpful assistant. Use this knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["kb_ids"] == [dataset_id], res

@pytest.mark.p2
def test_create_with_all_parameters(self, WebApiAuth, add_dataset_func):
dataset_id = add_dataset_func
payload = {
"name": "comprehensive_dialog",
"description": "A comprehensive test dialog",
"icon": "🤖",
"kb_ids": [dataset_id],
"top_n": 10,
"top_k": 2048,
"rerank_id": "",
"similarity_threshold": 0.2,
"vector_similarity_weight": 0.5,
"llm_setting": {"model": "gpt-4", "temperature": 0.8, "max_tokens": 1000},
"prompt_config": {"system": "You are a helpful assistant. Use this knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
data = res["data"]
assert data["name"] == "comprehensive_dialog", res
assert data["description"] == "A comprehensive test dialog", res
assert data["icon"] == "🤖", res
assert data["kb_ids"] == [dataset_id], res
assert data["top_n"] == 10, res
assert data["top_k"] == 2048, res
assert data["similarity_threshold"] == 0.2, res
assert data["vector_similarity_weight"] == 0.5, res

@pytest.mark.p3
def test_name_duplicated(self, WebApiAuth):
name = "duplicated_dialog"
payload = {"name": name, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p2
def test_optional_parameters(self, WebApiAuth):
payload = {
"name": "test_optional_params",
"prompt_config": {"system": "You are a helpful assistant. Optional param: {optional_param}", "parameters": [{"key": "optional_param", "optional": True}]},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

+ 204
- 0
test/testcases/test_web_api/test_dialog_app/test_delete_dialogs.py Прегледај датотеку

@@ -0,0 +1,204 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from concurrent.futures import ThreadPoolExecutor, as_completed

import pytest
from common import batch_create_dialogs, create_dialog, delete_dialog, list_dialogs
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth


@pytest.mark.usefixtures("clear_dialogs")
class TestAuthorization:
@pytest.mark.p1
@pytest.mark.parametrize(
"invalid_auth, expected_code, expected_message",
[
(None, 401, "<Unauthorized '401: Unauthorized'>"),
(RAGFlowWebApiAuth(INVALID_API_TOKEN), 401, "<Unauthorized '401: Unauthorized'>"),
],
ids=["empty_auth", "invalid_api_token"],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {"dialog_ids": [dialog_id]}
res = delete_dialog(invalid_auth, payload)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res


class TestDialogDelete:
@pytest.mark.p1
def test_delete_single_dialog(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 1, res

payload = {"dialog_ids": [dialog_id]}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"] is True, res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 0, res

@pytest.mark.p1
def test_delete_multiple_dialogs(self, WebApiAuth, add_dialogs_func):
_, dialog_ids = add_dialogs_func

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 5, res

payload = {"dialog_ids": dialog_ids}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"] is True, res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 0, res

@pytest.mark.p1
def test_delete_partial_dialogs(self, WebApiAuth, add_dialogs_func):
_, dialog_ids = add_dialogs_func

dialogs_to_delete = dialog_ids[:3]
payload = {"dialog_ids": dialogs_to_delete}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"] is True, res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 2, res

remaining_ids = [dialog["id"] for dialog in res["data"]]
for dialog_id in dialog_ids[3:]:
assert dialog_id in remaining_ids, res

@pytest.mark.p2
def test_delete_nonexistent_dialog(self, WebApiAuth):
fake_dialog_id = "nonexistent_dialog_id"
payload = {"dialog_ids": [fake_dialog_id]}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 103, res
assert "Only owner of dialog authorized for this operation." in res["message"], res

@pytest.mark.p2
def test_delete_empty_dialog_ids(self, WebApiAuth):
payload = {"dialog_ids": []}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p2
def test_delete_missing_dialog_ids(self, WebApiAuth):
payload = {}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 101, res
assert res["message"] == "required argument are missing: dialog_ids; ", res

@pytest.mark.p2
def test_delete_invalid_dialog_ids_format(self, WebApiAuth):
payload = {"dialog_ids": "not_a_list"}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 103, res
assert res["message"] == "Only owner of dialog authorized for this operation.", res

@pytest.mark.p2
def test_delete_mixed_valid_invalid_dialogs(self, WebApiAuth, add_dialog_func):
_, valid_dialog_id = add_dialog_func
invalid_dialog_id = "nonexistent_dialog_id"

payload = {"dialog_ids": [valid_dialog_id, invalid_dialog_id]}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 103, res
assert res["message"] == "Only owner of dialog authorized for this operation.", res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 1, res

@pytest.mark.p3
def test_delete_dialog_concurrent(self, WebApiAuth, add_dialogs_func):
_, dialog_ids = add_dialogs_func

count = len(dialog_ids)
with ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(delete_dialog, WebApiAuth, {"dialog_ids": [dialog_id]}) for dialog_id in dialog_ids]

responses = [future.result() for future in as_completed(futures)]

successful_deletions = sum(1 for response in responses if response["code"] == 0)
assert successful_deletions > 0, "No dialogs were successfully deleted"

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == count - successful_deletions, res

@pytest.mark.p3
def test_delete_dialog_idempotent(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func

payload = {"dialog_ids": [dialog_id]}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p3
def test_delete_large_batch_dialogs(self, WebApiAuth, add_document):
dataset_id, _ = add_document

dialog_ids = batch_create_dialogs(WebApiAuth, 50, [dataset_id])
assert len(dialog_ids) == 50, "Failed to create 50 dialogs"

payload = {"dialog_ids": dialog_ids}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"] is True, res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 0, res

@pytest.mark.p3
def test_delete_dialog_with_special_characters(self, WebApiAuth):
payload = {"name": "Dialog with 特殊字符 and émojis 🤖", "description": "Test dialog with special characters", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
create_res = create_dialog(WebApiAuth, payload)
assert create_res["code"] == 0, create_res
dialog_id = create_res["data"]["id"]

delete_payload = {"dialog_ids": [dialog_id]}
res = delete_dialog(WebApiAuth, delete_payload)
assert res["code"] == 0, res
assert res["data"] is True, res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 0, res

@pytest.mark.p3
def test_delete_dialog_preserves_other_user_dialogs(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func

payload = {"dialog_ids": [dialog_id]}
res = delete_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

+ 205
- 0
test/testcases/test_web_api/test_dialog_app/test_dialog_edge_cases.py Прегледај датотеку

@@ -0,0 +1,205 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
from common import create_dialog, delete_dialog, get_dialog, update_dialog


@pytest.mark.usefixtures("clear_dialogs")
class TestDialogEdgeCases:
@pytest.mark.p2
def test_create_dialog_with_tavily_api_key(self, WebApiAuth):
"""Test creating dialog with Tavily API key instead of knowledge base"""
payload = {
"name": "tavily_dialog",
"prompt_config": {"system": "You are a helpful assistant. Use this knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}], "tavily_api_key": "test_tavily_key"},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.skip
@pytest.mark.p2
def test_create_dialog_with_different_embedding_models(self, WebApiAuth):
"""Test creating dialog with knowledge bases that have different embedding models"""
# This test would require creating datasets with different embedding models
# For now, we'll test the error case with a mock scenario
payload = {
"name": "mixed_embedding_dialog",
"kb_ids": ["kb_with_model_a", "kb_with_model_b"],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
res = create_dialog(WebApiAuth, payload)
# This should fail due to different embedding models
assert res["code"] == 102, res
assert "Datasets use different embedding models" in res["message"], res

@pytest.mark.p2
def test_create_dialog_with_extremely_long_system_prompt(self, WebApiAuth):
"""Test creating dialog with very long system prompt"""
long_prompt = "You are a helpful assistant. " * 1000
payload = {"name": "long_prompt_dialog", "prompt_config": {"system": long_prompt, "parameters": []}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p2
def test_create_dialog_with_unicode_characters(self, WebApiAuth):
"""Test creating dialog with Unicode characters in various fields"""
payload = {
"name": "Unicode测试对话🤖",
"description": "测试Unicode字符支持 with émojis 🚀🌟",
"icon": "🤖",
"prompt_config": {"system": "你是一个有用的助手。You are helpful. Vous êtes utile. 🌍", "parameters": []},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["name"] == "Unicode测试对话🤖", res
assert res["data"]["description"] == "测试Unicode字符支持 with émojis 🚀🌟", res

@pytest.mark.p2
def test_create_dialog_with_extreme_parameter_values(self, WebApiAuth):
"""Test creating dialog with extreme parameter values"""
payload = {
"name": "extreme_params_dialog",
"top_n": 0,
"top_k": 1,
"similarity_threshold": 0.0,
"vector_similarity_weight": 1.0,
"prompt_config": {"system": "You are a helpful assistant.", "parameters": []},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["top_n"] == 0, res
assert res["data"]["top_k"] == 1, res
assert res["data"]["similarity_threshold"] == 0.0, res
assert res["data"]["vector_similarity_weight"] == 1.0, res

@pytest.mark.p2
def test_create_dialog_with_negative_parameter_values(self, WebApiAuth):
"""Test creating dialog with negative parameter values"""
payload = {
"name": "negative_params_dialog",
"top_n": -1,
"top_k": -100,
"similarity_threshold": -0.5,
"vector_similarity_weight": -0.3,
"prompt_config": {"system": "You are a helpful assistant.", "parameters": []},
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] in [0, 102], res

@pytest.mark.p2
def test_update_dialog_with_empty_kb_ids(self, WebApiAuth, add_dialog_func):
"""Test updating dialog to remove all knowledge bases"""
dataset_id, dialog_id = add_dialog_func
payload = {"dialog_id": dialog_id, "kb_ids": [], "prompt_config": {"system": "You are a helpful assistant without knowledge.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["kb_ids"] == [], res

@pytest.mark.p2
def test_update_dialog_with_null_values(self, WebApiAuth, add_dialog_func):
"""Test updating dialog with null/None values"""
dataset_id, dialog_id = add_dialog_func
payload = {"dialog_id": dialog_id, "description": None, "icon": None, "rerank_id": None, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p3
def test_dialog_with_complex_prompt_parameters(self, WebApiAuth, add_dataset_func):
"""Test dialog with complex prompt parameter configurations"""
payload = {
"name": "complex_params_dialog",
"prompt_config": {
"system": "You are {role} assistant. Use {knowledge} and consider {context}. Optional: {optional_param}",
"parameters": [{"key": "role", "optional": False}, {"key": "knowledge", "optional": True}, {"key": "context", "optional": False}, {"key": "optional_param", "optional": True}],
},
"kb_ids": [add_dataset_func],
}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p3
def test_dialog_with_malformed_prompt_parameters(self, WebApiAuth):
"""Test dialog with malformed prompt parameter configurations"""
payload = {
"name": "malformed_params_dialog",
"prompt_config": {
"system": "You are a helpful assistant.",
"parameters": [
{
"key": "",
"optional": False,
},
{"optional": True},
{
"key": "valid_param",
},
],
},
}
res = create_dialog(WebApiAuth, payload)

assert res["code"] in [0, 102], res

@pytest.mark.p3
def test_dialog_operations_with_special_ids(self, WebApiAuth):
"""Test dialog operations with special ID formats"""
special_ids = [
"00000000-0000-0000-0000-000000000000",
"ffffffff-ffff-ffff-ffff-ffffffffffff",
"12345678-1234-1234-1234-123456789abc",
]

for special_id in special_ids:
res = get_dialog(WebApiAuth, {"dialog_id": special_id})
assert res["code"] == 102, f"Should fail for ID: {special_id}"

res = delete_dialog(WebApiAuth, {"dialog_ids": [special_id]})
assert res["code"] == 103, f"Should fail for ID: {special_id}"

@pytest.mark.p3
def test_dialog_with_extremely_large_llm_settings(self, WebApiAuth):
"""Test dialog with very large LLM settings"""
large_llm_setting = {
"model": "gpt-4",
"temperature": 0.7,
"max_tokens": 999999,
"custom_param_" + "x" * 1000: "large_value_" + "y" * 1000,
}
payload = {"name": "large_llm_settings_dialog", "llm_setting": large_llm_setting, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = create_dialog(WebApiAuth, payload)
assert res["code"] == 0, res

@pytest.mark.p3
def test_concurrent_dialog_operations(self, WebApiAuth, add_dialog_func):
"""Test concurrent operations on the same dialog"""
from concurrent.futures import ThreadPoolExecutor, as_completed

_, dialog_id = add_dialog_func

def update_operation(i):
payload = {"dialog_id": dialog_id, "name": f"concurrent_update_{i}", "prompt_config": {"system": f"You are assistant number {i}.", "parameters": []}}
return update_dialog(WebApiAuth, payload)

with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(update_operation, i) for i in range(10)]

responses = [future.result() for future in as_completed(futures)]

successful_updates = sum(1 for response in responses if response["code"] == 0)
assert successful_updates > 0, "No updates succeeded"

res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res

+ 177
- 0
test/testcases/test_web_api/test_dialog_app/test_get_dialog.py Прегледај датотеку

@@ -0,0 +1,177 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
from common import create_dialog, get_dialog
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth


@pytest.mark.usefixtures("clear_dialogs")
class TestAuthorization:
@pytest.mark.p1
@pytest.mark.parametrize(
"invalid_auth, expected_code, expected_message",
[
(None, 401, "<Unauthorized '401: Unauthorized'>"),
(RAGFlowWebApiAuth(INVALID_API_TOKEN), 401, "<Unauthorized '401: Unauthorized'>"),
],
ids=["empty_auth", "invalid_api_token"],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message, add_dialog_func):
_, dialog_id = add_dialog_func
res = get_dialog(invalid_auth, {"dialog_id": dialog_id})
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res


class TestDialogGet:
@pytest.mark.p1
def test_get_existing_dialog(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res
data = res["data"]
assert data["id"] == dialog_id, res
assert "name" in data, res
assert "description" in data, res
assert "kb_ids" in data, res
assert "kb_names" in data, res
assert "prompt_config" in data, res
assert "llm_setting" in data, res
assert "top_n" in data, res
assert "top_k" in data, res
assert "similarity_threshold" in data, res
assert "vector_similarity_weight" in data, res

@pytest.mark.p1
def test_get_dialog_with_kb_names(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res
data = res["data"]
assert isinstance(data["kb_ids"], list), res
assert isinstance(data["kb_names"], list), res
assert len(data["kb_ids"]) == len(data["kb_names"]), res

@pytest.mark.p2
def test_get_nonexistent_dialog(self, WebApiAuth):
fake_dialog_id = "nonexistent_dialog_id"
res = get_dialog(WebApiAuth, {"dialog_id": fake_dialog_id})
assert res["code"] == 102, res
assert "Dialog not found" in res["message"], res

@pytest.mark.p2
def test_get_dialog_missing_id(self, WebApiAuth):
res = get_dialog(WebApiAuth, {})
assert res["code"] == 100, res
assert res["message"] == "<BadRequestKeyError '400: Bad Request'>", res

@pytest.mark.p2
def test_get_dialog_empty_id(self, WebApiAuth):
res = get_dialog(WebApiAuth, {"dialog_id": ""})
assert res["code"] == 102, res

@pytest.mark.p2
def test_get_dialog_invalid_id_format(self, WebApiAuth):
res = get_dialog(WebApiAuth, {"dialog_id": "invalid_format"})
assert res["code"] == 102, res

@pytest.mark.p3
def test_get_dialog_data_structure(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res
data = res["data"]

required_fields = [
"id",
"name",
"description",
"kb_ids",
"kb_names",
"prompt_config",
"llm_setting",
"top_n",
"top_k",
"similarity_threshold",
"vector_similarity_weight",
"create_time",
"update_time",
]
for field in required_fields:
assert field in data, f"Missing field: {field}"

assert isinstance(data["id"], str), res
assert isinstance(data["name"], str), res
assert isinstance(data["kb_ids"], list), res
assert isinstance(data["kb_names"], list), res
assert isinstance(data["prompt_config"], dict), res
assert isinstance(data["top_n"], int), res
assert isinstance(data["top_k"], int), res
assert isinstance(data["similarity_threshold"], (int, float)), res
assert isinstance(data["vector_similarity_weight"], (int, float)), res

@pytest.mark.p3
def test_get_dialog_prompt_config_structure(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res

prompt_config = res["data"]["prompt_config"]
assert "system" in prompt_config, res
assert "parameters" in prompt_config, res
assert isinstance(prompt_config["system"], str), res
assert isinstance(prompt_config["parameters"], list), res

@pytest.mark.p3
def test_get_dialog_with_multiple_kbs(self, WebApiAuth, add_dataset_func):
dataset_id1 = add_dataset_func
dataset_id2 = add_dataset_func

payload = {
"name": "multi_kb_dialog",
"kb_ids": [dataset_id1, dataset_id2],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
create_res = create_dialog(WebApiAuth, payload)
assert create_res["code"] == 0, create_res
dialog_id = create_res["data"]["id"]

res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res
data = res["data"]
assert len(data["kb_ids"]) == 2, res
assert len(data["kb_names"]) == 2, res
assert dataset_id1 in data["kb_ids"], res
assert dataset_id2 in data["kb_ids"], res

@pytest.mark.p3
def test_get_dialog_with_invalid_kb(self, WebApiAuth):
payload = {
"name": "invalid_kb_dialog",
"kb_ids": ["invalid_kb_id"],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
create_res = create_dialog(WebApiAuth, payload)
assert create_res["code"] == 0, create_res
dialog_id = create_res["data"]["id"]

res = get_dialog(WebApiAuth, {"dialog_id": dialog_id})
assert res["code"] == 0, res
data = res["data"]

assert len(data["kb_ids"]) == 0, res
assert len(data["kb_names"]) == 0, res

+ 210
- 0
test/testcases/test_web_api/test_dialog_app/test_list_dialogs.py Прегледај датотеку

@@ -0,0 +1,210 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
from common import batch_create_dialogs, create_dialog, list_dialogs
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth


@pytest.mark.usefixtures("clear_dialogs")
class TestAuthorization:
@pytest.mark.p1
@pytest.mark.parametrize(
"invalid_auth, expected_code, expected_message",
[
(None, 401, "<Unauthorized '401: Unauthorized'>"),
(RAGFlowWebApiAuth(INVALID_API_TOKEN), 401, "<Unauthorized '401: Unauthorized'>"),
],
ids=["empty_auth", "invalid_api_token"],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message):
res = list_dialogs(invalid_auth)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res


class TestDialogList:
@pytest.mark.p1
@pytest.mark.usefixtures("add_dialogs_func")
def test_list_empty_dialogs(self, WebApiAuth):
res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 5, res

@pytest.mark.p1
def test_list_multiple_dialogs(self, WebApiAuth, add_dialogs_func):
_, dialog_ids = add_dialogs_func
res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 5, res

returned_ids = [dialog["id"] for dialog in res["data"]]
for dialog_id in dialog_ids:
assert dialog_id in returned_ids, res

@pytest.mark.p2
@pytest.mark.usefixtures("add_dialogs_func")
def test_list_dialogs_data_structure(self, WebApiAuth):
res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 5, res

dialog = res["data"][0]
required_fields = [
"id",
"name",
"description",
"kb_ids",
"kb_names",
"prompt_config",
"llm_setting",
"top_n",
"top_k",
"similarity_threshold",
"vector_similarity_weight",
"create_time",
"update_time",
]
for field in required_fields:
assert field in dialog, f"Missing field: {field}"

assert isinstance(dialog["id"], str), res
assert isinstance(dialog["name"], str), res
assert isinstance(dialog["kb_ids"], list), res
assert isinstance(dialog["kb_names"], list), res
assert isinstance(dialog["prompt_config"], dict), res
assert isinstance(dialog["top_n"], int), res
assert isinstance(dialog["top_k"], int), res
assert isinstance(dialog["similarity_threshold"], (int, float)), res
assert isinstance(dialog["vector_similarity_weight"], (int, float)), res

@pytest.mark.p2
@pytest.mark.usefixtures("add_dialogs_func")
def test_list_dialogs_with_kb_names(self, WebApiAuth):
res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res

dialog = res["data"][0]
assert isinstance(dialog["kb_ids"], list), res
assert isinstance(dialog["kb_names"], list), res
assert len(dialog["kb_ids"]) == len(dialog["kb_names"]), res

@pytest.mark.p2
@pytest.mark.usefixtures("add_dialogs_func")
def test_list_dialogs_ordering(self, WebApiAuth):
res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 5, res

dialogs = res["data"]
for i in range(len(dialogs) - 1):
current_time = dialogs[i]["create_time"]
next_time = dialogs[i + 1]["create_time"]
assert current_time >= next_time, f"Dialogs not properly ordered: {current_time} should be >= {next_time}"

@pytest.mark.p3
@pytest.mark.usefixtures("clear_dialogs")
def test_list_dialogs_with_invalid_kb(self, WebApiAuth):
payload = {
"name": "invalid_kb_dialog",
"kb_ids": ["invalid_kb_id"],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
create_res = create_dialog(WebApiAuth, payload)
assert create_res["code"] == 0, create_res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 1, res

dialog = res["data"][0]

assert len(dialog["kb_ids"]) == 0, res
assert len(dialog["kb_names"]) == 0, res

@pytest.mark.p3
@pytest.mark.usefixtures("clear_dialogs")
def test_list_dialogs_with_multiple_kbs(self, WebApiAuth, add_dataset_func):
dataset_id1 = add_dataset_func
dataset_id2 = add_dataset_func

payload = {
"name": "multi_kb_dialog",
"kb_ids": [dataset_id1, dataset_id2],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
create_res = create_dialog(WebApiAuth, payload)
assert create_res["code"] == 0, create_res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 1, res

dialog = res["data"][0]
assert len(dialog["kb_ids"]) == 2, res
assert len(dialog["kb_names"]) == 2, res
assert dataset_id1 in dialog["kb_ids"], res
assert dataset_id2 in dialog["kb_ids"], res

@pytest.mark.p3
@pytest.mark.usefixtures("add_dialogs_func")
def test_list_dialogs_prompt_config_structure(self, WebApiAuth):
res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res

dialog = res["data"][0]
prompt_config = dialog["prompt_config"]
assert "system" in prompt_config, res
assert "parameters" in prompt_config, res
assert isinstance(prompt_config["system"], str), res
assert isinstance(prompt_config["parameters"], list), res

@pytest.mark.p3
@pytest.mark.usefixtures("clear_dialogs")
def test_list_dialogs_performance(self, WebApiAuth, add_document):
dataset_id, _ = add_document
dialog_ids = batch_create_dialogs(WebApiAuth, 100, [dataset_id])
assert len(dialog_ids) == 100, "Failed to create 100 dialogs"

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 100, res

returned_ids = [dialog["id"] for dialog in res["data"]]
for dialog_id in dialog_ids:
assert dialog_id in returned_ids, f"Dialog {dialog_id} not found in list"

@pytest.mark.p3
@pytest.mark.usefixtures("clear_dialogs")
def test_list_dialogs_with_mixed_kb_states(self, WebApiAuth, add_dataset_func):
valid_dataset_id = add_dataset_func

payload = {
"name": "mixed_kb_dialog",
"kb_ids": [valid_dataset_id, "invalid_kb_id"],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
create_res = create_dialog(WebApiAuth, payload)
assert create_res["code"] == 0, create_res

res = list_dialogs(WebApiAuth)
assert res["code"] == 0, res
assert len(res["data"]) == 1, res

dialog = res["data"][0]
assert len(dialog["kb_ids"]) == 1, res
assert dialog["kb_ids"][0] == valid_dataset_id, res
assert len(dialog["kb_names"]) == 1, res

+ 170
- 0
test/testcases/test_web_api/test_dialog_app/test_update_dialog.py Прегледај датотеку

@@ -0,0 +1,170 @@
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
from common import update_dialog
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth


@pytest.mark.usefixtures("clear_dialogs")
class TestAuthorization:
@pytest.mark.p1
@pytest.mark.parametrize(
"invalid_auth, expected_code, expected_message",
[
(None, 401, "<Unauthorized '401: Unauthorized'>"),
(RAGFlowWebApiAuth(INVALID_API_TOKEN), 401, "<Unauthorized '401: Unauthorized'>"),
],
ids=["empty_auth", "invalid_api_token"],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {"dialog_id": dialog_id, "name": "updated_name", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(invalid_auth, payload)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res


class TestDialogUpdate:
@pytest.mark.p1
def test_update_name(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
new_name = "updated_dialog_name"
payload = {"dialog_id": dialog_id, "name": new_name, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["name"] == new_name, res

@pytest.mark.p1
def test_update_description(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
new_description = "Updated description"
payload = {"dialog_id": dialog_id, "description": new_description, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["description"] == new_description, res

@pytest.mark.p1
def test_update_prompt_config(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
new_prompt_config = {"system": "You are an updated helpful assistant with {param1}.", "parameters": [{"key": "param1", "optional": False}]}
payload = {"dialog_id": dialog_id, "prompt_config": new_prompt_config}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["prompt_config"]["system"] == new_prompt_config["system"], res

@pytest.mark.p1
def test_update_kb_ids(self, WebApiAuth, add_dialog_func, add_dataset_func):
_, dialog_id = add_dialog_func
new_dataset_id = add_dataset_func
payload = {
"dialog_id": dialog_id,
"kb_ids": [new_dataset_id],
"prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]},
}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert new_dataset_id in res["data"]["kb_ids"], res

@pytest.mark.p1
def test_update_llm_settings(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
new_llm_setting = {"model": "gpt-4", "temperature": 0.9, "max_tokens": 2000}
payload = {"dialog_id": dialog_id, "llm_setting": new_llm_setting, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["llm_setting"]["model"] == "gpt-4", res
assert res["data"]["llm_setting"]["temperature"] == 0.9, res

@pytest.mark.p1
def test_update_retrieval_settings(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {
"dialog_id": dialog_id,
"top_n": 15,
"top_k": 4096,
"similarity_threshold": 0.3,
"vector_similarity_weight": 0.7,
"prompt_config": {"system": "You are a helpful assistant.", "parameters": []},
}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["top_n"] == 15, res
assert res["data"]["top_k"] == 4096, res
assert res["data"]["similarity_threshold"] == 0.3, res
assert res["data"]["vector_similarity_weight"] == 0.7, res

@pytest.mark.p2
def test_update_nonexistent_dialog(self, WebApiAuth):
fake_dialog_id = "nonexistent_dialog_id"
payload = {"dialog_id": fake_dialog_id, "name": "updated_name", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 102, res
assert "Dialog not found" in res["message"], res

@pytest.mark.p2
def test_update_with_invalid_prompt_config(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {"dialog_id": dialog_id, "prompt_config": {"system": "You are a helpful assistant.", "parameters": [{"key": "unused_param", "optional": False}]}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 102, res
assert "Parameter 'unused_param' is not used" in res["message"], res

@pytest.mark.p2
def test_update_with_knowledge_but_no_kb(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {"dialog_id": dialog_id, "kb_ids": [], "prompt_config": {"system": "You are a helpful assistant with knowledge: {knowledge}", "parameters": [{"key": "knowledge", "optional": True}]}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 102, res
assert "Please remove `{knowledge}` in system prompt" in res["message"], res

@pytest.mark.p2
def test_update_icon(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
new_icon = "🚀"
payload = {"dialog_id": dialog_id, "icon": new_icon, "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["icon"] == new_icon, res

@pytest.mark.p2
def test_update_rerank_id(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {"dialog_id": dialog_id, "rerank_id": "test_rerank_model", "prompt_config": {"system": "You are a helpful assistant.", "parameters": []}}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
assert res["data"]["rerank_id"] == "test_rerank_model", res

@pytest.mark.p3
def test_update_multiple_fields(self, WebApiAuth, add_dialog_func):
_, dialog_id = add_dialog_func
payload = {
"dialog_id": dialog_id,
"name": "multi_update_dialog",
"description": "Updated with multiple fields",
"icon": "🔄",
"top_n": 20,
"similarity_threshold": 0.4,
"prompt_config": {"system": "You are a multi-updated assistant.", "parameters": []},
}
res = update_dialog(WebApiAuth, payload)
assert res["code"] == 0, res
data = res["data"]
assert data["name"] == "multi_update_dialog", res
assert data["description"] == "Updated with multiple fields", res
assert data["icon"] == "🔄", res
assert data["top_n"] == 20, res
assert data["similarity_threshold"] == 0.4, res

Loading…
Откажи
Сачувај