@@ -543,6 +543,185 @@ async def mock_auser():
543543
544544 asyncio .run (run_test ())
545545
546+ def test_async_middleware_with_unauthenticated_user (self ):
547+ """
548+ Test that async middleware handles unauthenticated users correctly.
549+ """
550+
551+ async def run_test ():
552+ mock_response = Mock ()
553+ mock_user = Mock ()
554+ mock_user .is_authenticated = False # Not authenticated
555+
556+ async def async_get_response (request ):
557+ # Verify no distinct_id was set (no user)
558+ distinct_id = get_context_distinct_id ()
559+ self .assertIsNone (distinct_id )
560+ return mock_response
561+
562+ middleware = PosthogContextMiddleware (async_get_response )
563+ middleware .client = Mock ()
564+
565+ request = MockRequest (
566+ headers = {"X-POSTHOG-SESSION-ID" : "test-session" }, method = "GET"
567+ )
568+
569+ async def mock_auser ():
570+ return mock_user
571+
572+ request .auser = mock_auser
573+
574+ with new_context ():
575+ result = middleware (request )
576+ response = await result
577+ self .assertEqual (response , mock_response )
578+
579+ asyncio .run (run_test ())
580+
581+ def test_async_middleware_without_user_attribute (self ):
582+ """
583+ Test that async middleware handles requests without user attribute (no auth middleware).
584+ """
585+
586+ async def run_test ():
587+ mock_response = Mock ()
588+
589+ async def async_get_response (request ):
590+ return mock_response
591+
592+ middleware = PosthogContextMiddleware (async_get_response )
593+ middleware .client = Mock ()
594+
595+ # Request without auser method (no auth middleware)
596+ request = MockRequest (
597+ headers = {"X-POSTHOG-SESSION-ID" : "test-session" }, method = "GET"
598+ )
599+
600+ with new_context ():
601+ result = middleware (request )
602+ response = await result
603+ self .assertEqual (response , mock_response )
604+
605+ asyncio .run (run_test ())
606+
607+ def test_async_middleware_with_extra_tags (self ):
608+ """
609+ Test that async middleware works with extra_tags callback.
610+ """
611+
612+ async def run_test ():
613+ mock_response = Mock ()
614+
615+ def extra_tags_callback (request ):
616+ # Simple sync callback - should work
617+ return {"custom_tag" : "custom_value" }
618+
619+ async def async_get_response (request ):
620+ return mock_response
621+
622+ middleware = PosthogContextMiddleware (async_get_response )
623+ middleware .extra_tags = extra_tags_callback
624+ middleware .client = Mock ()
625+
626+ request = MockRequest (
627+ headers = {"X-POSTHOG-SESSION-ID" : "test-session" }, method = "GET"
628+ )
629+
630+ # Mock auser for no user
631+ async def mock_auser ():
632+ return None
633+
634+ request .auser = mock_auser
635+
636+ with new_context ():
637+ result = middleware (request )
638+ response = await result
639+ self .assertEqual (response , mock_response )
640+
641+ asyncio .run (run_test ())
642+
643+ def test_async_middleware_with_tag_map (self ):
644+ """
645+ Test that async middleware works with tag_map callback.
646+ """
647+
648+ async def run_test ():
649+ mock_response = Mock ()
650+
651+ def tag_map_callback (tags ):
652+ # Simple sync callback - should work
653+ tags ["mapped" ] = "yes"
654+ return tags
655+
656+ async def async_get_response (request ):
657+ return mock_response
658+
659+ middleware = PosthogContextMiddleware (async_get_response )
660+ middleware .tag_map = tag_map_callback
661+ middleware .client = Mock ()
662+
663+ request = MockRequest (
664+ headers = {"X-POSTHOG-SESSION-ID" : "test-session" }, method = "GET"
665+ )
666+
667+ # Mock auser for no user
668+ async def mock_auser ():
669+ return None
670+
671+ request .auser = mock_auser
672+
673+ with new_context ():
674+ result = middleware (request )
675+ response = await result
676+ self .assertEqual (response , mock_response )
677+
678+ asyncio .run (run_test ())
679+
680+ def test_async_middleware_user_extraction_with_all_headers (self ):
681+ """
682+ Test async middleware extracts all request info correctly.
683+ """
684+
685+ async def run_test ():
686+ mock_response = Mock ()
687+ mock_user = Mock ()
688+ mock_user .is_authenticated = True
689+ mock_user .pk = 456
690+ mock_user .
email = "[email protected] " 691+
692+ async def async_get_response (request ):
693+ # Verify all context was set correctly
694+ distinct_id = get_context_distinct_id ()
695+ session_id = get_context_session_id ()
696+ self .assertEqual (distinct_id , "456" )
697+ self .assertEqual (session_id , "async-sess-123" )
698+ return mock_response
699+
700+ middleware = PosthogContextMiddleware (async_get_response )
701+ middleware .client = Mock ()
702+
703+ request = MockRequest (
704+ headers = {
705+ "X-POSTHOG-SESSION-ID" : "async-sess-123" ,
706+ "X-Forwarded-For" : "192.168.1.1" ,
707+ "User-Agent" : "TestAgent/1.0" ,
708+ },
709+ method = "POST" ,
710+ path = "/api/test" ,
711+ )
712+
713+ async def mock_auser ():
714+ return mock_user
715+
716+ request .auser = mock_auser
717+
718+ with new_context ():
719+ result = middleware (request )
720+ response = await result
721+ self .assertEqual (response , mock_response )
722+
723+ asyncio .run (run_test ())
724+
546725
547726class TestPosthogContextMiddlewareHybrid (unittest .TestCase ):
548727 """Test hybrid middleware behavior with mixed sync/async chains"""
0 commit comments