test_: create private group tests (#6225)

* test_: create private group tests

* test_: set privileged False for jenkins

* test_: run baseline tests in rpc suite

* test_: address review comments

* test_: address review comments
This commit is contained in:
fbarbu15 2024-12-20 13:08:11 +02:00 committed by GitHub
parent 0cf556bdb9
commit 810468a57f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 305 additions and 154 deletions

View File

@ -0,0 +1,15 @@
from clients.rpc import RpcClient
from clients.services.service import Service
class AccountService(Service):
def __init__(self, client: RpcClient):
super().__init__(client, "accounts")
def get_accounts(self):
response = self.rpc_request("getAccounts")
return response.json()
def get_account_keypairs(self):
response = self.rpc_request("getKeypairs")
return response.json()

View File

@ -9,4 +9,4 @@ class Service:
def rpc_request(self, method: str, params=None):
full_method_name = f"{self.name}_{method}"
return self.rpc_client.rpc_request(full_method_name, params)
return self.rpc_client.rpc_valid_request(full_method_name, params)

View File

@ -0,0 +1,11 @@
from clients.rpc import RpcClient
from clients.services.service import Service
class SettingsService(Service):
def __init__(self, client: RpcClient):
super().__init__(client, "settings")
def get_settings(self):
response = self.rpc_request("getSettings")
return response.json()

View File

@ -0,0 +1,40 @@
from clients.rpc import RpcClient
from clients.services.service import Service
class WakuextService(Service):
def __init__(self, client: RpcClient):
super().__init__(client, "wakuext")
def send_contact_request(self, contact_id: str, message: str):
params = [{"id": contact_id, "message": message}]
response = self.rpc_request("sendContactRequest", params)
return response.json()
def accept_contact_request(self, request_id: str):
params = [{"id": request_id}]
response = self.rpc_request("acceptContactRequest", params)
return response.json()
def get_contacts(self):
response = self.rpc_request("contacts")
return response.json()
def send_message(self, contact_id: str, message: str):
params = [{"id": contact_id, "message": message}]
response = self.rpc_request("sendOneToOneMessage", params)
return response.json()
def start_messenger(self):
response = self.rpc_request("startMessenger")
json_response = response.json()
if "error" in json_response:
assert json_response["error"]["code"] == -32000
assert json_response["error"]["message"] == "messenger already started"
return
def create_group_chat_with_members(self, pubkey_list: list, group_chat_name: str):
params = [None, group_chat_name, pubkey_list]
response = self.rpc_request("createGroupChatWithMembers", params)
return response.json()

View File

@ -9,3 +9,6 @@ class WalletService(Service):
def get_balances_at_by_chain(self, chains: list, addresses: list, tokens: list):
params = [chains, addresses, tokens]
return self.rpc_request("getBalancesByChain", params)
def start_wallet(self):
return self.rpc_request("startWallet")

View File

@ -1,6 +1,7 @@
import io
import json
import logging
import string
import tarfile
import tempfile
import time
@ -10,12 +11,15 @@ import requests
import docker
import docker.errors
import os
from tenacity import retry, stop_after_delay, wait_fixed
from clients.signals import SignalClient
from clients.services.wallet import WalletService
from clients.services.wakuext import WakuextService
from clients.services.accounts import AccountService
from clients.services.settings import SettingsService
from clients.signals import SignalClient, SignalType
from clients.rpc import RpcClient
from conftest import option
from resources.constants import user_1, DEFAULT_DISPLAY_NAME, USER_DIR
from docker.errors import APIError
NANOSECONDS_PER_SECOND = 1_000_000_000
@ -24,7 +28,7 @@ class StatusBackend(RpcClient, SignalClient):
container = None
def __init__(self, await_signals=[]):
def __init__(self, await_signals=[], privileged=False):
if option.status_backend_url:
url = option.status_backend_url
@ -32,7 +36,7 @@ class StatusBackend(RpcClient, SignalClient):
self.docker_client = docker.from_env()
host_port = random.choice(option.status_backend_port_range)
self.container = self._start_container(host_port)
self.container = self._start_container(host_port, privileged)
url = f"http://127.0.0.1:{host_port}"
option.status_backend_port_range.remove(host_port)
@ -40,6 +44,7 @@ class StatusBackend(RpcClient, SignalClient):
self.api_url = f"{url}/statusgo"
self.ws_url = f"{url}".replace("http", "ws")
self.rpc_url = f"{url}/statusgo/CallRPC"
self.public_key = ""
RpcClient.__init__(self, self.rpc_url)
SignalClient.__init__(self, self.ws_url, await_signals)
@ -50,7 +55,12 @@ class StatusBackend(RpcClient, SignalClient):
websocket_thread.daemon = True
websocket_thread.start()
def _start_container(self, host_port):
self.wallet_service = WalletService(self)
self.wakuext_service = WakuextService(self)
self.accounts_service = AccountService(self)
self.settings_service = SettingsService(self)
def _start_container(self, host_port, privileged):
docker_project_name = option.docker_project_name
timestamp = int(time.time() * 1000) # Keep in sync with run_functional_tests.sh
@ -62,6 +72,7 @@ class StatusBackend(RpcClient, SignalClient):
container_args = {
"image": image_name,
"detach": True,
"privileged": privileged,
"name": container_name,
"labels": {"com.docker.compose.project": docker_project_name},
"entrypoint": [
@ -182,21 +193,26 @@ class StatusBackend(RpcClient, SignalClient):
def create_account_and_login(
self,
data_dir=USER_DIR,
display_name=DEFAULT_DISPLAY_NAME,
display_name=None,
password=user_1.password,
):
self.display_name = (
display_name if display_name else f"DISP_NAME_{''.join(random.choices(string.ascii_letters + string.digits + '_-', k=10))}"
)
method = "CreateAccountAndLogin"
data = {
"rootDataDir": data_dir,
"kdfIterations": 256000,
"displayName": display_name,
"displayName": self.display_name,
"password": password,
"customizationColor": "primary",
"logEnabled": True,
"logLevel": "DEBUG",
}
data = self._set_proxy_credentials(data)
return self.api_valid_request(method, data)
resp = self.api_valid_request(method, data)
self.node_login_event = self.find_signal_containing_pattern(SignalType.NODE_LOGIN.value, event_pattern=self.display_name)
return resp
def restore_account_and_login(
self,
@ -256,72 +272,34 @@ class StatusBackend(RpcClient, SignalClient):
# ToDo: change this part for waiting for `node.login` signal when websockets are migrated to StatusBackend
while time.time() - start_time <= timeout:
try:
self.rpc_valid_request(method="accounts_getKeypairs")
self.accounts_service.get_account_keypairs()
return
except AssertionError:
time.sleep(3)
raise TimeoutError(f"RPC client was not started after {timeout} seconds")
@retry(stop=stop_after_delay(10), wait=wait_fixed(0.5), reraise=True)
def start_messenger(self, params=[]):
method = "wakuext_startMessenger"
response = self.rpc_request(method, params)
json_response = response.json()
def container_pause(self):
if not self.container:
raise RuntimeError("Container is not initialized.")
self.container.pause()
logging.info(f"Container {self.container.name} paused.")
if "error" in json_response:
assert json_response["error"]["code"] == -32000
assert json_response["error"]["message"] == "messenger already started"
return
def container_unpause(self):
if not self.container:
raise RuntimeError("Container is not initialized.")
self.container.unpause()
logging.info(f"Container {self.container.name} unpaused.")
self.verify_is_valid_json_rpc_response(response)
def container_exec(self, command):
if not self.container:
raise RuntimeError("Container is not initialized.")
try:
exec_result = self.container.exec_run(cmd=["sh", "-c", command], stdout=True, stderr=True, tty=False)
if exec_result.exit_code != 0:
raise RuntimeError(f"Failed to execute command in container {self.container.id}:\n" f"OUTPUT: {exec_result.output.decode().strip()}")
return exec_result.output.decode().strip()
except APIError as e:
raise RuntimeError(f"API error during container execution: {str(e)}") from e
def start_wallet(self, params=[]):
method = "wallet_startWallet"
response = self.rpc_request(method, params)
self.verify_is_valid_json_rpc_response(response)
def get_settings(self, params=[]):
method = "settings_getSettings"
response = self.rpc_request(method, params)
self.verify_is_valid_json_rpc_response(response)
def get_accounts(self, params=[]):
method = "accounts_getAccounts"
response = self.rpc_request(method, params)
self.verify_is_valid_json_rpc_response(response)
return response.json()
def get_pubkey(self, display_name):
response = self.get_accounts()
accounts = response.get("result", [])
for account in accounts:
if account.get("name") == display_name:
return account.get("public-key")
raise ValueError(f"Public key not found for display name: {display_name}")
def send_contact_request(self, contact_id: str, message: str):
method = "wakuext_sendContactRequest"
params = [{"id": contact_id, "message": message}]
response = self.rpc_request(method, params)
self.verify_is_valid_json_rpc_response(response)
return response.json()
def accept_contact_request(self, chat_id: str):
method = "wakuext_acceptContactRequest"
params = [{"id": chat_id}]
response = self.rpc_request(method, params)
self.verify_is_valid_json_rpc_response(response)
return response.json()
def get_contacts(self):
method = "wakuext_contacts"
response = self.rpc_request(method)
self.verify_is_valid_json_rpc_response(response)
return response.json()
def send_message(self, contact_id: str, message: str):
method = "wakuext_sendOneToOneMessage"
params = [{"id": contact_id, "message": message}]
response = self.rpc_request(method, params)
self.verify_is_valid_json_rpc_response(response)
return response.json()
def find_public_key(self):
self.public_key = self.node_login_event.get("event", {}).get("settings", {}).get("public-key")

View File

@ -1,38 +1,28 @@
from time import sleep
from uuid import uuid4
import pytest
from test_cases import OneToOneMessageTestCase
from resources.constants import DEFAULT_DISPLAY_NAME
from test_cases import MessengerTestCase
from clients.signals import SignalType
from resources.enums import MessageContentType
@pytest.mark.rpc
class TestContactRequests(OneToOneMessageTestCase):
@pytest.mark.reliability
class TestContactRequests(MessengerTestCase):
@pytest.mark.rpc # until we have dedicated functional tests for this we can still run this test as part of the functional tests suite
@pytest.mark.dependency(name="test_contact_request_baseline")
def test_contact_request_baseline(self, execution_number=1):
await_signals = [
SignalType.MESSAGES_NEW.value,
SignalType.MESSAGE_DELIVERED.value,
]
message_text = f"test_contact_request_{execution_number}_{uuid4()}"
sender = self.initialize_backend(await_signals=self.await_signals)
receiver = self.initialize_backend(await_signals=self.await_signals)
sender = self.initialize_backend(await_signals=await_signals)
receiver = self.initialize_backend(await_signals=await_signals)
existing_contacts = receiver.wakuext_service.get_contacts()
pk_sender = sender.get_pubkey(DEFAULT_DISPLAY_NAME)
pk_receiver = receiver.get_pubkey(DEFAULT_DISPLAY_NAME)
existing_contacts = receiver.get_contacts()
if pk_sender in str(existing_contacts):
if sender.public_key in str(existing_contacts):
pytest.skip("Contact request was already sent for this sender<->receiver. Skipping test!!")
response = sender.send_contact_request(pk_receiver, message_text)
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.CONTACT_REQUEST.value)
response = sender.wakuext_service.send_contact_request(receiver.public_key, message_text)
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.CONTACT_REQUEST.value)[0]
messages_new_event = receiver.find_signal_containing_pattern(
SignalType.MESSAGES_NEW.value,
@ -44,7 +34,9 @@ class TestContactRequests(OneToOneMessageTestCase):
if "messages" in messages_new_event.get("event", {}):
signal_messages_texts.extend(message["text"] for message in messages_new_event["event"]["messages"] if "text" in message)
assert f"@{pk_sender} sent you a contact request" in signal_messages_texts, "Couldn't find the signal corresponding to the contact request"
assert (
f"@{sender.public_key} sent you a contact request" in signal_messages_texts
), "Couldn't find the signal corresponding to the contact request"
self.validate_signal_event_against_response(
signal_event=messages_new_event,
@ -67,23 +59,28 @@ class TestContactRequests(OneToOneMessageTestCase):
@pytest.mark.dependency(depends=["test_contact_request_baseline"])
@pytest.mark.skip(reason="Skipping until add_latency is implemented")
def test_contact_request_with_latency(self):
with self.add_latency():
self.test_contact_request_baseline()
# with self.add_latency():
# self.test_contact_request_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_contact_request_baseline"])
@pytest.mark.skip(reason="Skipping until add_packet_loss is implemented")
def test_contact_request_with_packet_loss(self):
with self.add_packet_loss():
self.test_contact_request_baseline()
# with self.add_packet_loss():
# self.test_contact_request_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_contact_request_baseline"])
@pytest.mark.skip(reason="Skipping until add_low_bandwith is implemented")
def test_contact_request_with_low_bandwidth(self):
with self.add_low_bandwith():
self.test_contact_request_baseline()
# with self.add_low_bandwith():
# self.test_contact_request_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_contact_request_baseline"])
@pytest.mark.skip(reason="Skipping until node_pause is implemented")
def test_contact_request_with_node_pause_30_seconds(self):
await_signals = [
SignalType.MESSAGES_NEW.value,
@ -91,11 +88,11 @@ class TestContactRequests(OneToOneMessageTestCase):
]
sender = self.initialize_backend(await_signals=await_signals)
receiver = self.initialize_backend(await_signals=await_signals)
pk_receiver = receiver.get_pubkey(DEFAULT_DISPLAY_NAME)
with self.node_pause(receiver):
message_text = f"test_contact_request_{uuid4()}"
sender.send_contact_request(pk_receiver, message_text)
response = sender.wakuext_service.send_contact_request(receiver.public_key, message_text)
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.CONTACT_REQUEST.value)[0]
sleep(30)
receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=message_text)
sender.wait_for_signal("messages.delivered")
receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=expected_message.get("id"))
sender.wait_for_signal(SignalType.MESSAGE_DELIVERED.value)

View File

@ -0,0 +1,77 @@
from time import sleep
from uuid import uuid4
import pytest
from test_cases import MessengerTestCase
from clients.signals import SignalType
from resources.enums import MessageContentType
@pytest.mark.usefixtures("setup_two_nodes")
@pytest.mark.reliability
class TestCreatePrivateGroups(MessengerTestCase):
@pytest.mark.rpc # until we have dedicated functional tests for this we can still run this test as part of the functional tests suite
@pytest.mark.dependency(name="test_create_private_group_baseline")
def test_create_private_group_baseline(self, private_groups_count=1):
self.make_contacts()
private_groups = []
for i in range(private_groups_count):
private_group_name = f"private_group_{i+1}_{uuid4()}"
response = self.sender.wakuext_service.create_group_chat_with_members([self.receiver.public_key], private_group_name)
expected_group_creation_msg = f"@{self.sender.public_key} created the group {private_group_name}"
expected_message = self.get_message_by_content_type(
response, content_type=MessageContentType.SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP.value, message_pattern=expected_group_creation_msg
)[0]
private_groups.append(expected_message)
sleep(0.01)
for i, expected_message in enumerate(private_groups):
messages_new_event = self.receiver.find_signal_containing_pattern(
SignalType.MESSAGES_NEW.value, event_pattern=expected_message.get("id"), timeout=60
)
self.validate_signal_event_against_response(
signal_event=messages_new_event,
expected_message=expected_message,
fields_to_validate={"text": "text"},
)
@pytest.mark.dependency(depends=["test_create_private_group_baseline"])
def test_multiple_one_create_private_groups(self):
self.test_create_private_group_baseline(private_groups_count=50)
@pytest.mark.dependency(depends=["test_create_private_group_baseline"])
@pytest.mark.skip(reason="Skipping until add_latency is implemented")
def test_create_private_groups_with_latency(self):
# with self.add_latency():
# self.test_create_private_group_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_create_private_group_baseline"])
@pytest.mark.skip(reason="Skipping until add_packet_loss is implemented")
def test_create_private_groups_with_packet_loss(self):
# with self.add_packet_loss():
# self.test_create_private_group_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_create_private_group_baseline"])
@pytest.mark.skip(reason="Skipping until add_low_bandwith is implemented")
def test_create_private_groups_with_low_bandwidth(self):
# with self.add_low_bandwith():
# self.test_create_private_group_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_create_private_group_baseline"])
def test_create_private_groups_with_node_pause_30_seconds(self):
self.make_contacts()
with self.node_pause(self.receiver):
private_group_name = f"private_group_{uuid4()}"
self.sender.wakuext_service.create_group_chat_with_members([self.receiver.public_key], private_group_name)
sleep(30)
self.receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=private_group_name)

View File

@ -1,35 +1,23 @@
from time import sleep
from uuid import uuid4
import pytest
from test_cases import OneToOneMessageTestCase
from resources.constants import DEFAULT_DISPLAY_NAME
from test_cases import MessengerTestCase
from clients.signals import SignalType
from resources.enums import MessageContentType
@pytest.mark.rpc
class TestOneToOneMessages(OneToOneMessageTestCase):
@pytest.fixture(scope="class", autouse=True)
def setup_nodes(self, request):
await_signals = [
SignalType.MESSAGES_NEW.value,
SignalType.MESSAGE_DELIVERED.value,
]
request.cls.sender = self.sender = self.initialize_backend(await_signals=await_signals)
request.cls.receiver = self.receiver = self.initialize_backend(await_signals=await_signals)
@pytest.mark.usefixtures("setup_two_nodes")
@pytest.mark.reliability
class TestOneToOneMessages(MessengerTestCase):
@pytest.mark.rpc # until we have dedicated functional tests for this we can still run this test as part of the functional tests suite
@pytest.mark.dependency(name="test_one_to_one_message_baseline")
def test_one_to_one_message_baseline(self, message_count=1):
pk_receiver = self.receiver.get_pubkey(DEFAULT_DISPLAY_NAME)
self.sender.send_contact_request(pk_receiver, "contact_request")
sent_messages = []
for i in range(message_count):
message_text = f"test_message_{i+1}_{uuid4()}"
response = self.sender.send_message(pk_receiver, message_text)
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.TEXT_PLAIN.value)
response = self.sender.wakuext_service.send_message(self.receiver.public_key, message_text)
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.TEXT_PLAIN.value)[0]
sent_messages.append(expected_message)
sleep(0.01)
@ -52,29 +40,32 @@ class TestOneToOneMessages(OneToOneMessageTestCase):
@pytest.mark.dependency(depends=["test_one_to_one_message_baseline"])
@pytest.mark.skip(reason="Skipping until add_latency is implemented")
def test_one_to_one_message_with_latency(self):
with self.add_latency():
self.test_one_to_one_message_baseline()
# with self.add_latency():
# self.test_one_to_one_message_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_one_to_one_message_baseline"])
@pytest.mark.skip(reason="Skipping until add_packet_loss is implemented")
def test_one_to_one_message_with_packet_loss(self):
with self.add_packet_loss():
self.test_one_to_one_message_baseline()
# with self.add_packet_loss():
# self.test_one_to_one_message_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_one_to_one_message_baseline"])
@pytest.mark.skip(reason="Skipping until add_low_bandwith is implemented")
def test_one_to_one_message_with_low_bandwidth(self):
with self.add_low_bandwith():
self.test_one_to_one_message_baseline()
# with self.add_low_bandwith():
# self.test_one_to_one_message_baseline()
# to be done in the next PR
pass
@pytest.mark.dependency(depends=["test_one_to_one_message_baseline"])
@pytest.mark.skip(reason="Skipping until node_pause is implemented")
def test_one_to_one_message_with_node_pause_30_seconds(self):
pk_receiver = self.receiver.get_pubkey("Receiver")
self.sender.send_contact_request(pk_receiver, "contact_request")
with self.node_pause(self.receiver):
message_text = f"test_message_{uuid4()}"
self.sender.send_message(pk_receiver, message_text)
self.sender.wakuext_service.send_message(self.receiver.public_key, message_text)
sleep(30)
self.receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=message_text)
self.sender.wait_for_signal("messages.delivered")
self.sender.wait_for_signal(SignalType.MESSAGE_DELIVERED.value)

View File

@ -11,7 +11,8 @@ from clients.services.wallet import WalletService
from clients.signals import SignalClient, SignalType
from clients.status_backend import RpcClient, StatusBackend
from conftest import option
from resources.constants import user_1, user_2, DEFAULT_DISPLAY_NAME
from resources.constants import user_1, user_2
from resources.enums import MessageContentType
class StatusDTestCase:
@ -151,47 +152,80 @@ class SignalTestCase(StatusDTestCase):
class NetworkConditionTestCase:
@contextmanager
def add_latency(self):
def add_latency(self, node, latency=300, jitter=50):
logging.info("Entering context manager: add_latency")
node.container_exec(f"apk add iproute2 && tc qdisc add dev eth0 root netem delay {latency}ms {jitter}ms distribution normal")
try:
# TODO: To be implemented when we have docker exec capability
yield
finally:
pass
logging.info("Exiting context manager: add_latency")
node.container_exec("tc qdisc del dev eth0 root")
@contextmanager
def add_packet_loss(self):
def add_packet_loss(self, node, packet_loss=2):
logging.info("Entering context manager: add_packet_loss")
node.container_exec(f"apk add iproute2 && tc qdisc add dev eth0 root netem loss {packet_loss}%")
try:
# TODO: To be implemented when we have docker exec capability
yield
finally:
pass
logging.info("Exiting context manager: add_packet_loss")
node.container_exec("tc qdisc del dev eth0 root netem")
@contextmanager
def add_low_bandwith(self):
def add_low_bandwith(self, node, rate="1mbit", burst="32kbit"):
logging.info("Entering context manager: add_low_bandwith")
node.container_exec(f"apk add iproute2 && tc qdisc add dev eth0 root tbf rate {rate} burst {burst}")
try:
# TODO: To be implemented when we have docker exec capability
yield
finally:
pass
logging.info("Exiting context manager: add_low_bandwith")
node.container_exec("tc qdisc del dev eth0 root")
@contextmanager
def node_pause(self, node):
logging.info("Entering context manager: node_pause")
node.container_pause()
try:
# TODO: To be implemented when we have docker exec capability
yield
finally:
pass
logging.info("Exiting context manager: node_pause")
node.container_unpause()
class OneToOneMessageTestCase(NetworkConditionTestCase):
class MessengerTestCase(NetworkConditionTestCase):
def initialize_backend(self, await_signals, display_name=DEFAULT_DISPLAY_NAME):
await_signals = [
SignalType.MESSAGES_NEW.value,
SignalType.MESSAGE_DELIVERED.value,
SignalType.NODE_LOGIN.value,
]
@pytest.fixture(scope="class", autouse=False)
def setup_two_nodes(self, request):
request.cls.sender = self.sender = self.initialize_backend(await_signals=self.await_signals)
request.cls.receiver = self.receiver = self.initialize_backend(await_signals=self.await_signals)
def initialize_backend(self, await_signals):
backend = StatusBackend(await_signals=await_signals)
backend.init_status_backend()
backend.create_account_and_login(display_name=display_name)
backend.start_messenger()
backend.create_account_and_login()
backend.find_public_key()
backend.wakuext_service.start_messenger()
return backend
def make_contacts(self):
existing_contacts = self.receiver.wakuext_service.get_contacts()
if self.sender.public_key in str(existing_contacts):
return
response = self.sender.wakuext_service.send_contact_request(self.receiver.public_key, "contact_request")
expected_message = self.get_message_by_content_type(response, content_type=MessageContentType.CONTACT_REQUEST.value)[0]
self.receiver.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=expected_message.get("id"))
self.receiver.wakuext_service.accept_contact_request(expected_message.get("id"))
accepted_signal = f"@{self.receiver.public_key} accepted your contact request"
self.sender.find_signal_containing_pattern(SignalType.MESSAGES_NEW.value, event_pattern=accepted_signal)
def validate_signal_event_against_response(self, signal_event, fields_to_validate, expected_message):
expected_message_id = expected_message.get("id")
signal_event_messages = signal_event.get("event", {}).get("messages")
@ -218,10 +252,15 @@ class OneToOneMessageTestCase(NetworkConditionTestCase):
"Details of mismatches:\n" + "\n".join(message_mismatch)
)
def get_message_by_content_type(self, response, content_type):
def get_message_by_content_type(self, response, content_type, message_pattern=""):
matched_messages = []
messages = response.get("result", {}).get("messages", [])
for message in messages:
if message.get("contentType") == content_type:
return message
raise ValueError(f"Failed to find a message with contentType '{content_type}' in response")
if message.get("contentType") != content_type:
continue
if not message_pattern or message_pattern in str(message):
matched_messages.append(message)
if matched_messages:
return matched_messages
else:
raise ValueError(f"Failed to find a message with contentType '{content_type}' in response")