Skip to content

Commit fe0778a

Browse files
test_: Code Migration from status-cli-tests added create_private_groups tests
1 parent 66d612c commit fe0778a

File tree

5 files changed

+211
-2
lines changed

5 files changed

+211
-2
lines changed

tests-functional/src/node/status_node.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ def send_contact_request(self, pubkey, message):
150150
params = [{"id": pubkey, "message": message}]
151151
return self.api.send_rpc_request("wakuext_sendContactRequest", params)
152152

153+
def accept_contact_request(self, chatId):
154+
params = [{"id": chatId}]
155+
return self.api.send_rpc_request("wakuext_acceptContactRequest", params)
156+
153157
def send_message(self, pubkey, message):
154158
params = [{"id": pubkey, "message": message}]
155159
return self.api.send_rpc_request("wakuext_sendOneToOneMessage", params)
@@ -163,3 +167,9 @@ def resume_process(self):
163167
if self.pid:
164168
logger.info(f"Resuming node with pid: {self.pid}")
165169
os.kill(self.pid, signal.SIGCONT)
170+
171+
def create_group_chat_with_members(self, pubkey_list, group_chat_name):
172+
if not isinstance(pubkey_list, list):
173+
raise TypeError("pubkey_list needs to be list")
174+
params = [None, group_chat_name, pubkey_list]
175+
return self.api.send_rpc_request("wakuext_createGroupChatWithMembers", params)

tests-functional/src/steps/common.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,14 @@ def accept_contact_request(self, sending_node=None, receiving_node_pk=None):
109109
if not receiving_node_pk:
110110
receiving_node_pk = self.first_node_pubkey
111111
sending_node.send_contact_request(receiving_node_pk, "hi")
112+
113+
def create_group_chat_with_timestamp(self, sender_node, member_list, private_group_name):
114+
timestamp = datetime.now().strftime("%H:%M:%S")
115+
response = sender_node.create_group_chat_with_members(member_list, private_group_name)
116+
response_messages = response["result"]["messages"]
117+
message_id = None
118+
for m in response_messages:
119+
if private_group_name in m["text"]:
120+
message_id = m["id"]
121+
break
122+
return timestamp, message_id
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import pytest
2+
from src.libs.common import delay
3+
from src.libs.custom_logger import get_custom_logger
4+
from src.steps.common import StepsCommon
5+
from constants import *
6+
from validators.contact_request_validator import ContactRequestValidator
7+
from validators.group_chat_validator import GroupChatValidator
8+
9+
logger = get_custom_logger(__name__)
10+
11+
12+
@pytest.mark.usefixtures("start_2_nodes")
13+
class TestCreatePrivateGroups(StepsCommon):
14+
def test_create_group_chat_baseline(self):
15+
num_private_groups = NUM_MESSAGES
16+
private_groups = []
17+
contact_request_sent = False
18+
19+
for i in range(num_private_groups):
20+
if i % 2 == 0:
21+
sender_node = self.first_node
22+
receiver_node = self.second_node
23+
receiver_pubkey = self.second_node_pubkey
24+
else:
25+
sender_node = self.second_node
26+
receiver_node = self.first_node
27+
receiver_pubkey = self.first_node_pubkey
28+
29+
if not contact_request_sent:
30+
display_name = f"{receiver_node.name}_user"
31+
contact_request_message = f"contact_request_{i}"
32+
timestamp, message_id, contact_request_message, response = self.send_and_wait_for_message(
33+
(sender_node, receiver_node), display_name, i
34+
)
35+
36+
if not response:
37+
raise AssertionError(f"Contact request failed between {sender_node.name} and {receiver_node.name}")
38+
39+
chat_id = response["result"]["chats"][0]["lastMessage"]["id"]
40+
accept_response = receiver_node.accept_contact_request(chat_id)
41+
42+
if not accept_response:
43+
raise AssertionError(
44+
f"Failed to accept contact request on {receiver_node.name} for chatId {chat_id}")
45+
46+
contact_request_sent = True
47+
delay(10)
48+
49+
group_name = f"private_group_from_{sender_node.name}_{i}"
50+
try:
51+
timestamp, message_id, response = self.create_and_validate_private_group(
52+
sender_node, [receiver_pubkey], group_name
53+
)
54+
55+
if not response:
56+
raise AssertionError("Failed to create private group. No valid response received.")
57+
else:
58+
print(f"Private group '{group_name}' created successfully with message ID: {message_id}")
59+
private_groups.append((timestamp, group_name, message_id, sender_node.name))
60+
61+
except AssertionError as e:
62+
print(f"Group creation validation failed: {e}")
63+
64+
self.first_node.stop()
65+
self.second_node.stop()
66+
67+
missing_private_groups = [
68+
(ts, name, mid, node) for ts, name, mid, node in private_groups if mid is None
69+
]
70+
71+
if missing_private_groups:
72+
formatted_missing_groups = [
73+
f"Timestamp: {ts}, GroupName: {msg}, ID: {mid}, Node: {node}" for ts, msg, mid, node in
74+
missing_private_groups
75+
]
76+
raise AssertionError(
77+
f"{len(missing_private_groups)} private groups out of {num_private_groups} were not created: " +
78+
"\n".join(formatted_missing_groups)
79+
)
80+
81+
def send_and_wait_for_message(self, nodes, display_name, index, timeout=10):
82+
sender_node, receiver_node = nodes
83+
84+
receiver_pubkey = receiver_node.get_pubkey(display_name)
85+
contact_request_message = f"contact_request_{index}"
86+
87+
timestamp, message_id, response = self.send_with_timestamp(
88+
sender_node.send_contact_request, receiver_pubkey, contact_request_message
89+
)
90+
91+
validator = ContactRequestValidator(response)
92+
validator.run_all_validations(receiver_pubkey, display_name, contact_request_message)
93+
94+
try:
95+
receiver_node.wait_for_signal("history.request.started", timeout)
96+
97+
messages_new_events = receiver_node.wait_for_complete_signal("messages.new", timeout)
98+
messages_new_event = None
99+
100+
for event in messages_new_events:
101+
if "chats" in event.get("event", {}):
102+
messages_new_event = event
103+
try:
104+
validator.validate_event_against_response(
105+
messages_new_event,
106+
fields_to_validate={
107+
"text": "text",
108+
"displayName": "displayName",
109+
"id": "id"
110+
}
111+
)
112+
break
113+
except AssertionError as validation_error:
114+
logger.error(f"Validation failed for event: {messages_new_event}, Error: {validation_error}")
115+
continue
116+
117+
if messages_new_event is None:
118+
raise ValueError("No 'messages.new' event with 'chats' data found within the timeout period.")
119+
120+
receiver_node.wait_for_signal("history.request.completed", timeout)
121+
122+
except (TimeoutError, ValueError) as e:
123+
logger.error(f"Signal validation failed: {str(e)}")
124+
return timestamp, message_id, contact_request_message, None
125+
126+
return timestamp, message_id, contact_request_message, response
127+
128+
def create_and_validate_private_group(self, node, members_pubkeys, group_name, timeout=10):
129+
timestamp, message_id, response = self.send_with_timestamp(
130+
node.create_group_chat_with_members, members_pubkeys, group_name
131+
)
132+
133+
if not response or "result" not in response or "chats" not in response["result"]:
134+
raise AssertionError("Invalid response structure. Expected 'result' with 'chats' list.")
135+
136+
chat_data = response["result"]["chats"][0]
137+
validator = GroupChatValidator(chat_data)
138+
139+
try:
140+
validator.validate_fields(
141+
{
142+
"id": "id",
143+
"name": group_name,
144+
"active": True,
145+
"chatType": 3,
146+
"members": [
147+
{"id": pubkey} for pubkey in members_pubkeys
148+
]
149+
}
150+
)
151+
except AssertionError as validation_error:
152+
raise AssertionError(f"Validation failed for group chat creation: {validation_error}")
153+
154+
try:
155+
node.wait_for_signal("history.request.completed", timeout)
156+
except TimeoutError:
157+
logger.error("Timeout waiting for group chat creation events.")
158+
return timestamp, message_id, None
159+
160+
return timestamp, message_id, response
161+
162+
def test_create_group_chat_with_latency(self):
163+
with self.add_latency():
164+
self.test_create_group_chat_baseline()
165+
166+
def test_create_group_chat_with_packet_loss(self):
167+
with self.add_packet_loss():
168+
self.test_create_group_chat_baseline()
169+
170+
def test_create_group_chat_with_low_bandwith(self):
171+
with self.add_low_bandwidth():
172+
self.test_create_group_chat_baseline()

tests-functional/validators/contact_request_validator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ def validate_chat_data(self, expected_chat_id, expected_display_name, expected_t
3232
)
3333

3434
actual_contact_request_state = last_message.get("contactRequestState")
35-
assert actual_contact_request_state == 1, (
36-
f"Unexpected contact request state: Expected '1', found '{actual_contact_request_state}'"
35+
assert actual_contact_request_state >= 1, (
36+
f"Unexpected contact request state: Expected '1' or higher, found '{actual_contact_request_state}'"
3737
)
3838

3939
assert "compressedKey" in last_message, "Missing 'compressedKey' in last message"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class GroupChatValidator:
2+
def __init__(self, response_data):
3+
self.response_data = response_data
4+
5+
def validate_fields(self, expected_fields):
6+
for field, expected_value in expected_fields.items():
7+
actual_value = self.response_data.get(field)
8+
if isinstance(expected_value, list):
9+
if not all(
10+
any(member.get("id") == ev["id"] for member in actual_value)
11+
for ev in expected_value
12+
):
13+
raise AssertionError(f"Validation failed: Mismatched members for field '{field}'")
14+
elif actual_value != expected_value:
15+
raise AssertionError(
16+
f"Validation failed for field '{field}': expected '{expected_value}', got '{actual_value}'")

0 commit comments

Comments
 (0)