Feat: message write testcase (#12417)

### What problem does this PR solve?

Write testcase for message web apis.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
This commit is contained in:
Lynn
2026-01-04 16:52:44 +08:00
committed by GitHub
parent 21ba9e6d72
commit a2211c200d
5 changed files with 401 additions and 0 deletions

View File

@ -38,9 +38,54 @@ def add_empty_raw_type_memory(request, WebApiAuth):
res = create_memory(WebApiAuth, payload)
memory_id = res["data"]["id"]
request.cls.memory_id = memory_id
request.cls.memory_type = payload["memory_type"]
return memory_id
@pytest.fixture(scope="class")
def add_empty_multiple_type_memory(request, WebApiAuth):
def cleanup():
memory_list_res = list_memory(WebApiAuth)
exist_memory_ids = [memory["id"] for memory in memory_list_res["data"]["memory_list"]]
for _memory_id in exist_memory_ids:
delete_memory(WebApiAuth, _memory_id)
request.addfinalizer(cleanup)
payload = {
"name": "test_memory_0",
"memory_type": ["raw"] + random.choices(["semantic", "episodic", "procedural"], k=random.randint(1, 3)),
"embd_id": "BAAI/bge-small-en-v1.5@Builtin",
"llm_id": "glm-4-flash@ZHIPU-AI"
}
res = create_memory(WebApiAuth, payload)
memory_id = res["data"]["id"]
request.cls.memory_id = memory_id
request.cls.memory_type = payload["memory_type"]
return memory_id
@pytest.fixture(scope="class")
def add_2_multiple_type_memory(request, WebApiAuth):
def cleanup():
memory_list_res = list_memory(WebApiAuth)
exist_memory_ids = [memory["id"] for memory in memory_list_res["data"]["memory_list"]]
for _memory_id in exist_memory_ids:
delete_memory(WebApiAuth, _memory_id)
request.addfinalizer(cleanup)
memory_ids = []
for i in range(2):
payload = {
"name": f"test_memory_{i}",
"memory_type": ["raw"] + random.choices(["semantic", "episodic", "procedural"], k=random.randint(1, 3)),
"embd_id": "BAAI/bge-small-en-v1.5@Builtin",
"llm_id": "glm-4-flash@ZHIPU-AI"
}
res = create_memory(WebApiAuth, payload)
memory_ids.append(res["data"]["id"])
request.cls.memory_ids = memory_ids
return memory_ids
@pytest.fixture(scope="class")
def add_memory_with_multiple_type_message_func(request, WebApiAuth):
def cleanup():

View File

@ -0,0 +1,145 @@
#
# 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 time
import uuid
import pytest
from test_web_api.common import list_memory_message, add_message
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth
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'>"),
],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message):
res = add_message(invalid_auth, {})
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res
@pytest.mark.usefixtures("add_empty_raw_type_memory")
class TestAddRawMessage:
@pytest.mark.p1
def test_add_raw_message(self, WebApiAuth):
memory_id = self.memory_id
agent_id = uuid.uuid4().hex
session_id = uuid.uuid4().hex
message_payload = {
"memory_id": [memory_id],
"agent_id": agent_id,
"session_id": session_id,
"user_id": "",
"user_input": "what is pineapple?",
"agent_response": """
A pineapple is a tropical fruit known for its sweet, tangy flavor and distinctive, spiky appearance. Here are the key facts:
Scientific Name: Ananas comosus
Physical Description: It has a tough, spiky, diamond-patterned outer skin (rind) that is usually green, yellow, or brownish. Inside, the juicy yellow flesh surrounds a fibrous core.
Growth: Unlike most fruits, pineapples do not grow on trees. They grow from a central stem as a composite fruit, meaning they are formed from many individual berries that fuse together around the core. They grow on a short, leafy plant close to the ground.
Uses: Pineapples are eaten fresh, cooked, grilled, juiced, or canned. They are a popular ingredient in desserts, fruit salads, savory dishes (like pizzas or ham glazes), smoothies, and cocktails.
Nutrition: They are a good source of Vitamin C, manganese, and contain an enzyme called bromelain, which aids in digestion and can tenderize meat.
Symbolism: The pineapple is a traditional symbol of hospitality and welcome in many cultures.
Are you asking about the fruit itself, or its use in a specific context?
"""
}
add_res = add_message(WebApiAuth, message_payload)
assert add_res["code"] == 0, add_res
time.sleep(2) # make sure refresh to index before search
message_res = list_memory_message(WebApiAuth, memory_id, params={"agent_id": agent_id, "keywords": session_id})
assert message_res["code"] == 0, message_res
assert message_res["data"]["messages"]["total_count"] > 0
for message in message_res["data"]["messages"]["message_list"]:
assert message["agent_id"] == agent_id, message
assert message["session_id"] == session_id, message
@pytest.mark.usefixtures("add_empty_multiple_type_memory")
class TestAddMultipleTypeMessage:
@pytest.mark.p1
def test_add_multiple_type_message(self, WebApiAuth):
memory_id = self.memory_id
agent_id = uuid.uuid4().hex
session_id = uuid.uuid4().hex
message_payload = {
"memory_id": [memory_id],
"agent_id": agent_id,
"session_id": session_id,
"user_id": "",
"user_input": "what is pineapple?",
"agent_response": """
A pineapple is a tropical fruit known for its sweet, tangy flavor and distinctive, spiky appearance. Here are the key facts:
Scientific Name: Ananas comosus
Physical Description: It has a tough, spiky, diamond-patterned outer skin (rind) that is usually green, yellow, or brownish. Inside, the juicy yellow flesh surrounds a fibrous core.
Growth: Unlike most fruits, pineapples do not grow on trees. They grow from a central stem as a composite fruit, meaning they are formed from many individual berries that fuse together around the core. They grow on a short, leafy plant close to the ground.
Uses: Pineapples are eaten fresh, cooked, grilled, juiced, or canned. They are a popular ingredient in desserts, fruit salads, savory dishes (like pizzas or ham glazes), smoothies, and cocktails.
Nutrition: They are a good source of Vitamin C, manganese, and contain an enzyme called bromelain, which aids in digestion and can tenderize meat.
Symbolism: The pineapple is a traditional symbol of hospitality and welcome in many cultures.
Are you asking about the fruit itself, or its use in a specific context?
"""
}
add_res = add_message(WebApiAuth, message_payload)
assert add_res["code"] == 0, add_res
time.sleep(2) # make sure refresh to index before search
message_res = list_memory_message(WebApiAuth, memory_id, params={"agent_id": agent_id, "keywords": session_id})
assert message_res["code"] == 0, message_res
assert message_res["data"]["messages"]["total_count"] > 0
for message in message_res["data"]["messages"]["message_list"]:
assert message["agent_id"] == agent_id, message
assert message["session_id"] == session_id, message
@pytest.mark.usefixtures("add_2_multiple_type_memory")
class TestAddToMultipleMemory:
@pytest.mark.p1
def test_add_to_multiple_memory(self, WebApiAuth):
memory_ids = self.memory_ids
agent_id = uuid.uuid4().hex
session_id = uuid.uuid4().hex
message_payload = {
"memory_id": memory_ids,
"agent_id": agent_id,
"session_id": session_id,
"user_id": "",
"user_input": "what is pineapple?",
"agent_response": """
A pineapple is a tropical fruit known for its sweet, tangy flavor and distinctive, spiky appearance. Here are the key facts:
Scientific Name: Ananas comosus
Physical Description: It has a tough, spiky, diamond-patterned outer skin (rind) that is usually green, yellow, or brownish. Inside, the juicy yellow flesh surrounds a fibrous core.
Growth: Unlike most fruits, pineapples do not grow on trees. They grow from a central stem as a composite fruit, meaning they are formed from many individual berries that fuse together around the core. They grow on a short, leafy plant close to the ground.
Uses: Pineapples are eaten fresh, cooked, grilled, juiced, or canned. They are a popular ingredient in desserts, fruit salads, savory dishes (like pizzas or ham glazes), smoothies, and cocktails.
Nutrition: They are a good source of Vitamin C, manganese, and contain an enzyme called bromelain, which aids in digestion and can tenderize meat.
Symbolism: The pineapple is a traditional symbol of hospitality and welcome in many cultures.
Are you asking about the fruit itself, or its use in a specific context?
"""
}
add_res = add_message(WebApiAuth, message_payload)
assert add_res["code"] == 0, add_res
time.sleep(2) # make sure refresh to index before search
for memory_id in memory_ids:
message_res = list_memory_message(WebApiAuth, memory_id, params={"agent_id": agent_id, "keywords": session_id})
assert message_res["code"] == 0, message_res
assert message_res["data"]["messages"]["total_count"] > 0
for message in message_res["data"]["messages"]["message_list"]:
assert message["agent_id"] == agent_id, message
assert message["session_id"] == session_id, message

View File

@ -0,0 +1,54 @@
#
# 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 random
import pytest
from test_web_api.common import forget_message, list_memory_message, get_message_content
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth
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'>"),
],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message):
res = forget_message(invalid_auth, "empty_memory_id", 0)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res
@pytest.mark.usefixtures("add_memory_with_5_raw_message_func")
class TestForgetMessage:
@pytest.mark.p1
def test_forget_message(self, WebApiAuth):
memory_id = self.memory_id
list_res = list_memory_message(WebApiAuth, memory_id)
assert list_res["code"] == 0, list_res
assert len(list_res["data"]["messages"]["message_list"]) > 0
message = random.choice(list_res["data"]["messages"]["message_list"])
res = forget_message(WebApiAuth, memory_id, message["message_id"])
assert res["code"] == 0, res
forgot_message_res = get_message_content(WebApiAuth, memory_id, message["message_id"])
assert forgot_message_res["code"] == 0, forgot_message_res
assert forgot_message_res["data"]["forget_at"] not in ["-", ""], forgot_message_res

View File

@ -0,0 +1,82 @@
#
# 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 test_web_api.common import search_message, list_memory_message
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth
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'>"),
],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message):
res = search_message(invalid_auth)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res
@pytest.mark.usefixtures("add_memory_with_multiple_type_message_func")
class TestSearchMessage:
@pytest.mark.p1
def test_query(self, WebApiAuth):
memory_id = self.memory_id
list_res = list_memory_message(WebApiAuth, memory_id)
assert list_res["code"] == 0, list_res
assert list_res["data"]["messages"]["total_count"] > 0
query = "Coriander is a versatile herb with two main edible parts. What's its name can refer to?"
res = search_message(WebApiAuth, {"memory_id": memory_id, "query": query})
assert res["code"] == 0, res
assert len(res["data"]) > 0
@pytest.mark.p2
def test_query_with_agent_filter(self, WebApiAuth):
memory_id = self.memory_id
list_res = list_memory_message(WebApiAuth, memory_id)
assert list_res["code"] == 0, list_res
assert list_res["data"]["messages"]["total_count"] > 0
agent_id = self.agent_id
query = "Coriander is a versatile herb with two main edible parts. What's its name can refer to?"
res = search_message(WebApiAuth, {"memory_id": memory_id, "query": query, "agent_id": agent_id})
assert res["code"] == 0, res
assert len(res["data"]) > 0
for message in res["data"]:
assert message["agent_id"] == agent_id, message
@pytest.mark.p2
def test_query_with_not_default_params(self, WebApiAuth):
memory_id = self.memory_id
list_res = list_memory_message(WebApiAuth, memory_id)
assert list_res["code"] == 0, list_res
assert list_res["data"]["messages"]["total_count"] > 0
query = "Coriander is a versatile herb with two main edible parts. What's its name can refer to?"
params = {
"similarity_threshold": 0.1,
"keywords_similarity_weight": 0.6,
"top_n": 4
}
res = search_message(WebApiAuth, {"memory_id": memory_id, "query": query, **params})
assert res["code"] == 0, res
assert len(res["data"]) > 0
assert len(res["data"]) <= params["top_n"]

View File

@ -0,0 +1,75 @@
#
# 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 random
import pytest
from test_web_api.common import update_message_status, list_memory_message, get_message_content
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth
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'>"),
],
)
def test_auth_invalid(self, invalid_auth, expected_code, expected_message):
res = update_message_status(invalid_auth, "empty_memory_id", 0, False)
assert res["code"] == expected_code, res
assert res["message"] == expected_message, res
@pytest.mark.usefixtures("add_memory_with_5_raw_message_func")
class TestUpdateMessageStatus:
@pytest.mark.p1
def test_update_to_false(self, WebApiAuth):
memory_id = self.memory_id
list_res = list_memory_message(WebApiAuth, memory_id)
assert list_res["code"] == 0, list_res
assert len(list_res["data"]["messages"]["message_list"]) > 0
message = random.choice(list_res["data"]["messages"]["message_list"])
res = update_message_status(WebApiAuth, memory_id, message["message_id"], False)
assert res["code"] == 0, res
updated_message_res = get_message_content(WebApiAuth, memory_id, message["message_id"])
assert updated_message_res["code"] == 0, res
assert not updated_message_res["data"]["status"], res
@pytest.mark.p1
def test_update_to_true(self, WebApiAuth):
memory_id = self.memory_id
list_res = list_memory_message(WebApiAuth, memory_id)
assert list_res["code"] == 0, list_res
assert len(list_res["data"]["messages"]["message_list"]) > 0
# set 1 random message to false first
message = random.choice(list_res["data"]["messages"]["message_list"])
set_to_false_res = update_message_status(WebApiAuth, memory_id, message["message_id"], False)
assert set_to_false_res["code"] == 0, set_to_false_res
updated_message_res = get_message_content(WebApiAuth, memory_id, message["message_id"])
assert updated_message_res["code"] == 0, set_to_false_res
assert not updated_message_res["data"]["status"], updated_message_res
# set to true
set_to_true_res = update_message_status(WebApiAuth, memory_id, message["message_id"], True)
assert set_to_true_res["code"] == 0, set_to_true_res
res = get_message_content(WebApiAuth, memory_id, message["message_id"])
assert res["code"] == 0, res
assert res["data"]["status"], res