@@ -20,6 +20,7 @@ const mockState = vi.hoisted(() => ({
2020 isAuthenticated : false ,
2121 } ,
2222 convexUser : null as { occupation ?: string } | null ,
23+ actorKey : null as string | null ,
2324 detectPlatform : vi . fn ( ( ) => "mac" ) ,
2425} ) ) ;
2526
@@ -40,13 +41,18 @@ vi.mock("@/lib/PosthogUtils", () => ({
4041 detectPlatform : mockState . detectPlatform ,
4142} ) ) ;
4243
44+ vi . mock ( "@/hooks/use-actor-key" , ( ) => ( {
45+ useActorKey : ( ) => mockState . actorKey ,
46+ } ) ) ;
47+
4348describe ( "usePostHogIdentify" , ( ) => {
4449 beforeEach ( ( ) => {
4550 vi . clearAllMocks ( ) ;
4651 vi . stubGlobal ( "__APP_VERSION__" , "2.0.13-test" ) ;
4752 mockState . auth . user = null ;
4853 mockState . convexAuth . isAuthenticated = false ;
4954 mockState . convexUser = null ;
55+ mockState . actorKey = null ;
5056 mockState . detectPlatform . mockReturnValue ( "mac" ) ;
5157 } ) ;
5258
@@ -58,6 +64,7 @@ describe("usePostHogIdentify", () => {
5864 lastName : "Smith" ,
5965 } ;
6066 mockState . convexAuth . isAuthenticated = true ;
67+ mockState . actorKey = "user_123" ;
6168
6269 renderHook ( ( ) => usePostHogIdentify ( ) ) ;
6370
@@ -73,25 +80,57 @@ describe("usePostHogIdentify", () => {
7380 expect ( mockState . posthog . reset ) . not . toHaveBeenCalled ( ) ;
7481 } ) ;
7582
76- it ( "re-registers static telemetry properties after logout reset" , ( ) => {
83+ it ( "identifies guests with their guestId and does not call reset" , ( ) => {
84+ mockState . auth . user = null ;
85+ mockState . convexAuth . isAuthenticated = false ;
86+ mockState . actorKey = "guest_abc" ;
87+
7788 renderHook ( ( ) => usePostHogIdentify ( ) ) ;
7889
79- expect ( mockState . posthog . reset ) . toHaveBeenCalledTimes ( 1 ) ;
90+ expect ( mockState . posthog . identify ) . toHaveBeenCalledWith ( "guest_abc" , { } ) ;
8091 expect ( mockState . posthog . register ) . toHaveBeenCalledWith ( {
81- environment : import . meta. env . MODE ,
82- platform : "mac" ,
83- version : "2.0.13-test" ,
92+ user_id : "guest_abc" ,
8493 } ) ;
94+ expect ( mockState . posthog . reset ) . not . toHaveBeenCalled ( ) ;
8595 } ) ;
8696
87- it ( "resets and re-registers static telemetry properties when auth changes from logged in to logged out" , ( ) => {
97+ it ( "does nothing while the actor key is still resolving" , ( ) => {
98+ mockState . auth . user = null ;
99+ mockState . actorKey = null ;
100+
101+ renderHook ( ( ) => usePostHogIdentify ( ) ) ;
102+
103+ expect ( mockState . posthog . identify ) . not . toHaveBeenCalled ( ) ;
104+ expect ( mockState . posthog . register ) . not . toHaveBeenCalled ( ) ;
105+ expect ( mockState . posthog . reset ) . not . toHaveBeenCalled ( ) ;
106+ } ) ;
107+
108+ it ( "is idempotent across re-renders with the same guest actor key" , ( ) => {
109+ mockState . auth . user = null ;
110+ mockState . actorKey = "guest_abc" ;
111+
112+ const { rerender } = renderHook ( ( ) => usePostHogIdentify ( ) ) ;
113+
114+ expect ( mockState . posthog . identify ) . toHaveBeenCalledTimes ( 1 ) ;
115+ expect ( mockState . posthog . register ) . toHaveBeenCalledTimes ( 1 ) ;
116+
117+ rerender ( ) ;
118+ rerender ( ) ;
119+
120+ expect ( mockState . posthog . identify ) . toHaveBeenCalledTimes ( 1 ) ;
121+ expect ( mockState . posthog . register ) . toHaveBeenCalledTimes ( 1 ) ;
122+ expect ( mockState . posthog . reset ) . not . toHaveBeenCalled ( ) ;
123+ } ) ;
124+
125+ it ( "resets and re-registers static telemetry properties when an authed user signs out into a guest session" , ( ) => {
88126 mockState . auth . user = {
89127 id : "user_123" ,
90128 email : "user@example.com" ,
91129 firstName : "Taylor" ,
92130 lastName : "Smith" ,
93131 } ;
94132 mockState . convexAuth . isAuthenticated = true ;
133+ mockState . actorKey = "user_123" ;
95134
96135 const { rerender } = renderHook ( ( ) => usePostHogIdentify ( ) ) ;
97136
@@ -106,6 +145,7 @@ describe("usePostHogIdentify", () => {
106145
107146 mockState . auth . user = null ;
108147 mockState . convexAuth . isAuthenticated = false ;
148+ mockState . actorKey = "guest_abc" ;
109149
110150 rerender ( ) ;
111151
@@ -115,7 +155,44 @@ describe("usePostHogIdentify", () => {
115155 platform : "mac" ,
116156 version : "2.0.13-test" ,
117157 } ) ;
118- expect ( mockState . posthog . identify ) . not . toHaveBeenCalled ( ) ;
158+ expect ( mockState . posthog . identify ) . toHaveBeenCalledWith ( "guest_abc" , { } ) ;
159+ expect ( mockState . posthog . register ) . toHaveBeenCalledWith ( {
160+ user_id : "guest_abc" ,
161+ } ) ;
162+ } ) ;
163+
164+ it ( "aliases a guest into an authed user without calling reset on guest→authed promotion" , ( ) => {
165+ mockState . auth . user = null ;
166+ mockState . convexAuth . isAuthenticated = false ;
167+ mockState . actorKey = "guest_abc" ;
168+
169+ const { rerender } = renderHook ( ( ) => usePostHogIdentify ( ) ) ;
170+
171+ expect ( mockState . posthog . identify ) . toHaveBeenCalledWith ( "guest_abc" , { } ) ;
172+
173+ vi . clearAllMocks ( ) ;
174+
175+ mockState . auth . user = {
176+ id : "user_123" ,
177+ email : "user@example.com" ,
178+ firstName : "Taylor" ,
179+ lastName : "Smith" ,
180+ } ;
181+ mockState . convexAuth . isAuthenticated = true ;
182+ mockState . actorKey = "user_123" ;
183+
184+ rerender ( ) ;
185+
186+ expect ( mockState . posthog . reset ) . not . toHaveBeenCalled ( ) ;
187+ expect ( mockState . posthog . identify ) . toHaveBeenCalledWith ( "user_123" , {
188+ email : "user@example.com" ,
189+ name : "Taylor Smith" ,
190+ first_name : "Taylor" ,
191+ last_name : "Smith" ,
192+ } ) ;
193+ expect ( mockState . posthog . register ) . toHaveBeenCalledWith ( {
194+ user_id : "user_123" ,
195+ } ) ;
119196 } ) ;
120197
121198 it ( "adds trimmed occupation when the Convex user has one" , ( ) => {
@@ -126,6 +203,7 @@ describe("usePostHogIdentify", () => {
126203 lastName : "Smith" ,
127204 } ;
128205 mockState . convexAuth . isAuthenticated = true ;
206+ mockState . actorKey = "user_123" ;
129207 mockState . convexUser = { occupation : " Platform Engineer " } ;
130208
131209 renderHook ( ( ) => usePostHogIdentify ( ) ) ;
@@ -147,6 +225,7 @@ describe("usePostHogIdentify", () => {
147225 lastName : "Smith" ,
148226 } ;
149227 mockState . convexAuth . isAuthenticated = true ;
228+ mockState . actorKey = "user_123" ;
150229 mockState . convexUser = { occupation : " " } ;
151230
152231 renderHook ( ( ) => usePostHogIdentify ( ) ) ;
0 commit comments