@@ -98,6 +98,68 @@ def test_default_state_directory_unchanged(self):
9898 assert "my-app" in state_dir_str
9999 assert "Replicated" in state_dir_str
100100
101+ def test_client_has_machine_id (self ):
102+ """Test that client initializes with a machine_id."""
103+ client = ReplicatedClient (publishable_key = "pk_test_123" , app_slug = "my-app" )
104+ assert hasattr (client , "_machine_id" )
105+ assert client ._machine_id is not None
106+ assert isinstance (client ._machine_id , str )
107+ assert len (client ._machine_id ) == 64 # SHA256 hash
108+
109+ @patch ("replicated.http_client.httpx.Client" )
110+ def test_instance_has_machine_id_from_client (self , mock_httpx ):
111+ """Test that instances created from client have the client's machine_id."""
112+ from replicated .resources import Instance
113+
114+ mock_response = Mock ()
115+ mock_response .is_success = True
116+ mock_response .json .return_value = {
117+ "customer" : {
118+ "id" : "customer_123" ,
119+ 120+ "name" : "test user" ,
121+ "serviceToken" : "service_token_123" ,
122+ "instanceId" : "instance_123" ,
123+ }
124+ }
125+
126+ mock_client = Mock ()
127+ mock_client .request .return_value = mock_response
128+ mock_httpx .return_value = mock_client
129+
130+ client = ReplicatedClient (publishable_key = "pk_test_123" , app_slug = "my-app" )
131+ customer = client .
customer .
get_or_create (
"[email protected] " )
132+ instance = customer .get_or_create_instance ()
133+
134+ assert isinstance (instance , Instance )
135+ assert hasattr (instance , "_machine_id" )
136+ assert instance ._machine_id == client ._machine_id
137+
138+ @patch ("replicated.http_client.httpx.Client" )
139+ def test_instance_uses_machine_id_in_headers (self , mock_httpx ):
140+ """Test that instance methods use machine_id as cluster ID in headers."""
141+ from replicated .resources import Instance
142+
143+ mock_response = Mock ()
144+ mock_response .is_success = True
145+ mock_response .json .return_value = {}
146+
147+ mock_client = Mock ()
148+ mock_client .request .return_value = mock_response
149+ mock_httpx .return_value = mock_client
150+
151+ client = ReplicatedClient (publishable_key = "pk_test_123" , app_slug = "my-app" )
152+ instance = Instance (client , "customer_123" , "instance_123" )
153+
154+ # Send a metric
155+ instance .send_metric ("test_metric" , 42 )
156+
157+ # Verify the request was made with correct headers
158+ call_args = mock_client .request .call_args
159+ headers = call_args [1 ]["headers" ]
160+ assert "X-Replicated-ClusterID" in headers
161+ assert headers ["X-Replicated-ClusterID" ] == client ._machine_id
162+
101163
102164class TestAsyncReplicatedClient :
103165 @pytest .mark .asyncio
@@ -168,3 +230,74 @@ async def test_default_state_directory_unchanged(self):
168230 state_dir_str = str (client .state_manager ._state_dir )
169231 assert "my-app" in state_dir_str
170232 assert "Replicated" in state_dir_str
233+
234+ @pytest .mark .asyncio
235+ async def test_client_has_machine_id (self ):
236+ """Test that async client initializes with a machine_id."""
237+ client = AsyncReplicatedClient (publishable_key = "pk_test_123" , app_slug = "my-app" )
238+ assert hasattr (client , "_machine_id" )
239+ assert client ._machine_id is not None
240+ assert isinstance (client ._machine_id , str )
241+ assert len (client ._machine_id ) == 64 # SHA256 hash
242+
243+ @pytest .mark .asyncio
244+ async def test_instance_has_machine_id_from_client (self ):
245+ """Test that async instances have the client's machine_id."""
246+ from replicated .resources import AsyncInstance
247+
248+ with patch ("replicated.http_client.httpx.AsyncClient" ) as mock_httpx :
249+ mock_response = Mock ()
250+ mock_response .is_success = True
251+ mock_response .json .return_value = {
252+ "customer" : {
253+ "id" : "customer_123" ,
254+ 255+ "name" : "test user" ,
256+ "serviceToken" : "service_token_123" ,
257+ "instanceId" : "instance_123" ,
258+ }
259+ }
260+
261+ mock_client = Mock ()
262+ mock_client .request .return_value = mock_response
263+ mock_httpx .return_value = mock_client
264+
265+ client = AsyncReplicatedClient (
266+ publishable_key = "pk_test_123" , app_slug = "my-app"
267+ )
268+ customer = await client .
customer .
get_or_create (
"[email protected] " )
269+ instance = await customer .get_or_create_instance ()
270+
271+ assert isinstance (instance , AsyncInstance )
272+ assert hasattr (instance , "_machine_id" )
273+ assert instance ._machine_id == client ._machine_id
274+
275+ @pytest .mark .asyncio
276+ async def test_instance_uses_machine_id_in_headers (self ):
277+ """Test that async instance methods use machine_id as cluster ID in headers."""
278+ from unittest .mock import AsyncMock
279+
280+ from replicated .resources import AsyncInstance
281+
282+ with patch ("replicated.http_client.httpx.AsyncClient" ) as mock_httpx :
283+ mock_response = Mock ()
284+ mock_response .is_success = True
285+ mock_response .json .return_value = {}
286+
287+ mock_client = Mock ()
288+ mock_client .request = AsyncMock (return_value = mock_response )
289+ mock_httpx .return_value = mock_client
290+
291+ client = AsyncReplicatedClient (
292+ publishable_key = "pk_test_123" , app_slug = "my-app"
293+ )
294+ instance = AsyncInstance (client , "customer_123" , "instance_123" )
295+
296+ # Send a metric
297+ await instance .send_metric ("test_metric" , 42 )
298+
299+ # Verify the request was made with correct headers
300+ call_args = mock_client .request .call_args
301+ headers = call_args [1 ]["headers" ]
302+ assert "X-Replicated-ClusterID" in headers
303+ assert headers ["X-Replicated-ClusterID" ] == client ._machine_id
0 commit comments