1
+ # pylint: disable=redefined-outer-name
2
+ # pylint: disable=unused-argument
3
+ # pylint: disable=unused-variable
4
+ # pylint: disable=too-many-arguments
5
+
6
+
7
+ import asyncio
1
8
from collections .abc import Callable
9
+ from typing import Any
10
+ from unittest .mock import AsyncMock
2
11
3
12
import pytest
4
13
import socketio
9
18
from pytest_simcore .helpers .utils_envs import setenvs_from_dict
10
19
from settings_library .rabbit import RabbitSettings
11
20
from simcore_service_payments .services .socketio import (
21
+ SOCKET_IO_PAYMENT_COMPLETED_EVENT ,
12
22
emit_to_frontend ,
13
23
get_rabbitmq_settings ,
14
24
)
24
34
def app_environment (
25
35
monkeypatch : pytest .MonkeyPatch ,
26
36
app_environment : EnvVarsDict ,
37
+ with_disabled_postgres : None ,
27
38
rabbit_env_vars_dict : EnvVarsDict , # rabbitMQ settings from 'rabbit' service
28
39
):
29
40
# set environs
@@ -44,7 +55,7 @@ async def test_socketio_setup():
44
55
45
56
46
57
@pytest .fixture
47
- async def socketio_aiohttp_server (app : FastAPI , aiohttp_server : Callable ) -> TestServer :
58
+ async def socketio_server (app : FastAPI , aiohttp_server : Callable ) -> TestServer :
48
59
"""
49
60
this emulates the webserver setup: socketio server with
50
61
an aiopika manager that attaches an aiohttp web app
@@ -60,35 +71,81 @@ async def socketio_aiohttp_server(app: FastAPI, aiohttp_server: Callable) -> Tes
60
71
client_manager = server_manager ,
61
72
)
62
73
63
- @sio_server .event ()
64
- async def connect (sid , environ ):
65
- ...
74
+ @sio_server .event
75
+ async def connect (sid : str , environ ):
76
+ print ("connecting" , sid )
77
+
78
+ @sio_server .on (SOCKET_IO_PAYMENT_COMPLETED_EVENT )
79
+ async def on_payment (sid , data ):
80
+ print (sid , Any )
81
+
82
+ @sio_server .event
83
+ async def disconnect (sid : str ):
84
+ print ("disconnecting" , sid )
66
85
67
86
sio_server .attach (aiohttp_app )
68
87
88
+ # starts server
69
89
return await aiohttp_server (aiohttp_app )
70
90
71
91
72
- async def test_emit_socketio_event_to_front_end (
73
- app : FastAPI , socketio_aiohttp_server : TestServer
92
+ @pytest .fixture
93
+ async def create_sio_client (socketio_server : TestServer ):
94
+ server_url = socketio_server .make_url ("/" )
95
+ _clients = []
96
+
97
+ async def _ ():
98
+ cli = socketio .AsyncClient (
99
+ logger = True ,
100
+ engineio_logger = True ,
101
+ )
102
+
103
+ # https://python-socketio.readthedocs.io/en/stable/client.html#connecting-to-a-server
104
+ # Allows WebSocket transport and disconnect HTTP long-polling
105
+ await cli .connect (f"{ server_url } " , transports = ["websocket" ])
106
+
107
+ _clients .append (cli )
108
+
109
+ return cli
110
+
111
+ yield _
112
+
113
+ for client in _clients :
114
+ await client .disconnect ()
115
+
116
+
117
+ async def test_emit_message_as_external_process_to_frontend_client (
118
+ app : FastAPI , create_sio_client : Callable
74
119
):
75
- server_url = socketio_aiohttp_server .make_url ("/" )
120
+ """
121
+ front-end -> socketio client (many different clients)
122
+ webserver -> socketio server (one/more replicas)
123
+ payments -> Sends messages to clients from external processes (one/more replicas)
124
+ """
76
125
77
- # create a client
78
- async with socketio .AsyncSimpleClient ( logger = True , engineio_logger = True ) as sio :
126
+ # emulates front-end receiving message
127
+ client_1 : socketio .AsyncClient = await create_sio_client ()
79
128
80
- # https://python-socketio.readthedocs.io/en/stable/client.html#connecting-to-a-server
81
- # connect to a server
82
- await sio .connect (server_url , transports = ["websocket" ])
83
- session_client_id = sio .sid
129
+ @client_1 .on (SOCKET_IO_PAYMENT_COMPLETED_EVENT )
130
+ async def on_event (data ):
131
+ print ("client1" , data )
84
132
85
- # emit from external
86
- await emit_to_frontend (
87
- app , event_name = "event" , data = {"foo" : "bar" }, to = session_client_id
88
- )
133
+ on_event_spy = AsyncMock (wraps = on_event )
134
+
135
+ await client_1 .emit (SOCKET_IO_PAYMENT_COMPLETED_EVENT , data = "hoi1" )
136
+
137
+ # TODO: better to do this from a different process??
138
+ # emit from external process
139
+ await emit_to_frontend (
140
+ app ,
141
+ event_name = SOCKET_IO_PAYMENT_COMPLETED_EVENT ,
142
+ data = {"foo" : "bar" },
143
+ # to=client_1.sid,
144
+ )
145
+
146
+ await client_1 .emit (SOCKET_IO_PAYMENT_COMPLETED_EVENT , data = "hoi2" )
89
147
90
- # client receives it
91
- event : list = await sio .receive (timeout = 5 )
92
- event_name , * event_kwargs = event
148
+ await client_1 .sleep (1 )
149
+ await asyncio .sleep (1 )
93
150
94
- assert event_name == "event"
151
+ on_event_spy . assert_called ()
0 commit comments