Skip to content

Commit e6c95e7

Browse files
authored
chore: Add tests for Reference.listen() (#851)
* chore: Add unit tests for `Reference.listen()` * Integration test for rtdb listeners * fix lint
1 parent e5618c0 commit e6c95e7

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

integration/test_db.py

+32
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import collections
1717
import json
1818
import os
19+
import time
1920

2021
import pytest
2122

@@ -245,6 +246,37 @@ def test_delete(self, testref):
245246
ref.delete()
246247
assert ref.get() is None
247248

249+
class TestListenOperations:
250+
"""Test cases for listening to changes to node values."""
251+
252+
def test_listen(self, testref):
253+
self.events = []
254+
def callback(event):
255+
self.events.append(event)
256+
257+
python = testref.parent
258+
registration = python.listen(callback)
259+
try:
260+
ref = python.child('users').push()
261+
assert ref.path == '/_adminsdk/python/users/' + ref.key
262+
assert ref.get() == ''
263+
264+
self.wait_for(self.events, count=2)
265+
assert len(self.events) == 2
266+
267+
assert self.events[1].event_type == 'put'
268+
assert self.events[1].path == '/users/' + ref.key
269+
assert self.events[1].data == ''
270+
finally:
271+
registration.close()
272+
273+
@classmethod
274+
def wait_for(cls, events, count=1, timeout_seconds=5):
275+
must_end = time.time() + timeout_seconds
276+
while time.time() < must_end:
277+
if len(events) >= count:
278+
return
279+
raise pytest.fail('Timed out while waiting for events')
248280

249281
class TestAdvancedQueries:
250282
"""Test cases for advanced interactions via the db.Query interface."""

tests/test_db.py

+43
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,49 @@ def callback(_):
535535
finally:
536536
testutils.cleanup_apps()
537537

538+
@pytest.mark.parametrize(
539+
'url,emulator_host,expected_base_url,expected_namespace',
540+
[
541+
# Production URLs with no override:
542+
('https://test.firebaseio.com', None, 'https://test.firebaseio.com/.json', None),
543+
('https://test.firebaseio.com/', None, 'https://test.firebaseio.com/.json', None),
544+
545+
# Production URLs with emulator_host override:
546+
('https://test.firebaseio.com', 'localhost:9000', 'http://localhost:9000/.json',
547+
'test'),
548+
('https://test.firebaseio.com/', 'localhost:9000', 'http://localhost:9000/.json',
549+
'test'),
550+
551+
# Emulator URL with no override.
552+
('http://localhost:8000/?ns=test', None, 'http://localhost:8000/.json', 'test'),
553+
554+
# emulator_host is ignored when the original URL is already emulator.
555+
('http://localhost:8000/?ns=test', 'localhost:9999', 'http://localhost:8000/.json',
556+
'test'),
557+
]
558+
)
559+
def test_listen_sse_client(self, url, emulator_host, expected_base_url, expected_namespace,
560+
mocker):
561+
if emulator_host:
562+
os.environ[_EMULATOR_HOST_ENV_VAR] = emulator_host
563+
564+
try:
565+
firebase_admin.initialize_app(testutils.MockCredential(), {'databaseURL' : url})
566+
ref = db.reference()
567+
mock_sse_client = mocker.patch('firebase_admin._sseclient.SSEClient')
568+
mock_callback = mocker.Mock()
569+
ref.listen(mock_callback)
570+
args, kwargs = mock_sse_client.call_args
571+
assert args[0] == expected_base_url
572+
if expected_namespace:
573+
assert kwargs.get('params') == {'ns': expected_namespace}
574+
else:
575+
assert kwargs.get('params') == {}
576+
finally:
577+
if _EMULATOR_HOST_ENV_VAR in os.environ:
578+
del os.environ[_EMULATOR_HOST_ENV_VAR]
579+
testutils.cleanup_apps()
580+
538581
def test_listener_session(self):
539582
firebase_admin.initialize_app(testutils.MockCredential(), {
540583
'databaseURL' : 'https://test.firebaseio.com',

0 commit comments

Comments
 (0)