@@ -3,10 +3,23 @@ import {
33 buildInternalTelemetryEvent ,
44 captureInternalTelemetry ,
55 captureInternalTelemetryBatched ,
6- flushInternalTelemetryBatchesForTests ,
76 workspaceDistinctId ,
87} from '../telemetry.js' ;
98
9+ // Mock the posthog module
10+ vi . mock ( '../posthog.js' , ( ) => {
11+ const mockCapture = vi . fn ( ) ;
12+ const mockShutdown = vi . fn ( ) . mockResolvedValue ( undefined ) ;
13+ return {
14+ getPostHogClient : vi . fn ( ( ) => ( {
15+ capture : mockCapture ,
16+ shutdown : mockShutdown ,
17+ } ) ) ,
18+ flushAllPostHogClients : vi . fn ( ) . mockResolvedValue ( undefined ) ,
19+ telemetryEnabled : vi . fn ( ( ) => true ) ,
20+ } ;
21+ } ) ;
22+
1023describe ( 'server telemetry' , ( ) => {
1124 beforeEach ( ( ) => {
1225 vi . clearAllMocks ( ) ;
@@ -31,9 +44,13 @@ describe('server telemetry', () => {
3144 } ) ) . toThrow ( / M i s s i n g r e q u i r e d p r o p e r t i e s / ) ;
3245 } ) ;
3346
34- it ( 'sends capture events to PostHog with origin in properties' , async ( ) => {
35- const fetchMock = vi . fn ( ) . mockResolvedValue ( new Response ( null , { status : 200 } ) ) ;
36- vi . stubGlobal ( 'fetch' , fetchMock ) ;
47+ it ( 'sends capture events to PostHog via the SDK' , async ( ) => {
48+ const { getPostHogClient } = await import ( '../posthog.js' ) ;
49+ const mockCapture = vi . fn ( ) ;
50+ ( getPostHogClient as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
51+ capture : mockCapture ,
52+ shutdown : vi . fn ( ) . mockResolvedValue ( undefined ) ,
53+ } ) ;
3754
3855 await captureInternalTelemetry (
3956 {
@@ -57,21 +74,26 @@ describe('server telemetry', () => {
5774 } ,
5875 ) ;
5976
60- expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
61- const [ url , init ] = fetchMock . mock . calls [ 0 ] as [ string , RequestInit ] ;
62- expect ( url ) . toBe ( 'https://us.i.posthog.com/capture/' ) ;
63- expect ( init . method ) . toBe ( 'POST' ) ;
64-
65- const payload = JSON . parse ( String ( init . body ) ) ;
66- expect ( payload . event ) . toBe ( 'relaycast_server_search_executed' ) ;
67- expect ( payload . properties . origin_surface ) . toBe ( 'sdk' ) ;
68- expect ( payload . properties . origin_client ) . toBe ( '@relaycast/sdk-ts' ) ;
69- expect ( payload . properties . origin_version ) . toBe ( '0.3.1' ) ;
77+ expect ( mockCapture ) . toHaveBeenCalledTimes ( 1 ) ;
78+ expect ( mockCapture ) . toHaveBeenCalledWith ( {
79+ distinctId : workspaceDistinctId ( 'ws_123' ) ,
80+ event : 'relaycast_server_search_executed' ,
81+ properties : expect . objectContaining ( {
82+ workspace_id : 'ws_123' ,
83+ origin_surface : 'sdk' ,
84+ origin_client : '@relaycast/sdk-ts' ,
85+ origin_version : '0.3.1' ,
86+ } ) ,
87+ } ) ;
7088 } ) ;
7189
7290 it ( 'is a no-op when POSTHOG_API_KEY is missing' , async ( ) => {
73- const fetchMock = vi . fn ( ) ;
74- vi . stubGlobal ( 'fetch' , fetchMock ) ;
91+ const { getPostHogClient } = await import ( '../posthog.js' ) ;
92+ const mockCapture = vi . fn ( ) ;
93+ ( getPostHogClient as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
94+ capture : mockCapture ,
95+ shutdown : vi . fn ( ) . mockResolvedValue ( undefined ) ,
96+ } ) ;
7597
7698 await captureInternalTelemetry (
7799 {
@@ -93,12 +115,17 @@ describe('server telemetry', () => {
93115 } ,
94116 ) ;
95117
96- expect ( fetchMock ) . not . toHaveBeenCalled ( ) ;
118+ expect ( mockCapture ) . not . toHaveBeenCalled ( ) ;
97119 } ) ;
98120
99121 it ( 'is a no-op when opt-out env vars are enabled' , async ( ) => {
100- const fetchMock = vi . fn ( ) ;
101- vi . stubGlobal ( 'fetch' , fetchMock ) ;
122+ const { getPostHogClient, telemetryEnabled } = await import ( '../posthog.js' ) ;
123+ const mockCapture = vi . fn ( ) ;
124+ ( getPostHogClient as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
125+ capture : mockCapture ,
126+ shutdown : vi . fn ( ) . mockResolvedValue ( undefined ) ,
127+ } ) ;
128+ ( telemetryEnabled as ReturnType < typeof vi . fn > ) . mockReturnValue ( false ) ;
102129
103130 await captureInternalTelemetry (
104131 {
@@ -144,13 +171,17 @@ describe('server telemetry', () => {
144171 } ,
145172 ) ;
146173
147- await flushInternalTelemetryBatchesForTests ( ) ;
148- expect ( fetchMock ) . not . toHaveBeenCalled ( ) ;
174+ expect ( mockCapture ) . not . toHaveBeenCalled ( ) ;
149175 } ) ;
150176
151177 it ( 'does not auto-disable based on ENVIRONMENT name' , async ( ) => {
152- const fetchMock = vi . fn ( ) . mockResolvedValue ( new Response ( null , { status : 200 } ) ) ;
153- vi . stubGlobal ( 'fetch' , fetchMock ) ;
178+ const { getPostHogClient, telemetryEnabled } = await import ( '../posthog.js' ) ;
179+ const mockCapture = vi . fn ( ) ;
180+ ( getPostHogClient as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
181+ capture : mockCapture ,
182+ shutdown : vi . fn ( ) . mockResolvedValue ( undefined ) ,
183+ } ) ;
184+ ( telemetryEnabled as ReturnType < typeof vi . fn > ) . mockReturnValue ( true ) ;
154185
155186 await captureInternalTelemetry (
156187 {
@@ -173,58 +204,63 @@ describe('server telemetry', () => {
173204 } ,
174205 ) ;
175206
176- expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
207+ expect ( mockCapture ) . toHaveBeenCalledTimes ( 1 ) ;
177208 } ) ;
178209
179- it ( 'batches multiple events into one /batch request' , async ( ) => {
180- const fetchMock = vi . fn ( ) . mockResolvedValue ( new Response ( null , { status : 200 } ) ) ;
181- vi . stubGlobal ( 'fetch' , fetchMock ) ;
182-
183- const env = {
184- ENVIRONMENT : 'production' ,
185- POSTHOG_API_KEY : 'phc_test' ,
186- POSTHOG_HOST : 'https://us.i.posthog.com/' ,
187- } as any ;
188-
189- const p1 = captureInternalTelemetryBatched ( env , {
190- event : 'relaycast_server_search_executed' ,
191- distinct_id : workspaceDistinctId ( 'ws_123' ) ,
192- origin : {
193- origin_surface : 'sdk' ,
194- origin_client : '@relaycast/sdk-ts' ,
195- origin_version : '0.3.1' ,
196- } ,
197- properties : {
198- workspace_id : 'ws_123' ,
199- query_length : 2 ,
200- result_count : 1 ,
201- } ,
210+ it ( 'captureInternalTelemetryBatched delegates to the SDK (which handles batching internally)' , async ( ) => {
211+ const { getPostHogClient } = await import ( '../posthog.js' ) ;
212+ const mockCapture = vi . fn ( ) ;
213+ ( getPostHogClient as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
214+ capture : mockCapture ,
215+ shutdown : vi . fn ( ) . mockResolvedValue ( undefined ) ,
202216 } ) ;
203- const p2 = captureInternalTelemetryBatched ( env , {
204- event : 'relaycast_server_search_executed' ,
205- distinct_id : workspaceDistinctId ( 'ws_123' ) ,
206- origin : {
207- origin_surface : 'sdk' ,
208- origin_client : '@relaycast/sdk-ts' ,
209- origin_version : '0.3.1' ,
217+
218+ const p1 = captureInternalTelemetryBatched (
219+ {
220+ ENVIRONMENT : 'production' ,
221+ POSTHOG_API_KEY : 'phc_test' ,
222+ POSTHOG_HOST : 'https://us.i.posthog.com/' ,
223+ } as any ,
224+ {
225+ event : 'relaycast_server_search_executed' ,
226+ distinct_id : workspaceDistinctId ( 'ws_123' ) ,
227+ origin : {
228+ origin_surface : 'sdk' ,
229+ origin_client : '@relaycast/sdk-ts' ,
230+ origin_version : '0.3.1' ,
231+ } ,
232+ properties : {
233+ workspace_id : 'ws_123' ,
234+ query_length : 2 ,
235+ result_count : 1 ,
236+ } ,
210237 } ,
211- properties : {
212- workspace_id : 'ws_123' ,
213- query_length : 4 ,
214- result_count : 2 ,
238+ ) ;
239+ const p2 = captureInternalTelemetryBatched (
240+ {
241+ ENVIRONMENT : 'production' ,
242+ POSTHOG_API_KEY : 'phc_test' ,
243+ POSTHOG_HOST : 'https://us.i.posthog.com/' ,
244+ } as any ,
245+ {
246+ event : 'relaycast_server_search_executed' ,
247+ distinct_id : workspaceDistinctId ( 'ws_123' ) ,
248+ origin : {
249+ origin_surface : 'sdk' ,
250+ origin_client : '@relaycast/sdk-ts' ,
251+ origin_version : '0.3.1' ,
252+ } ,
253+ properties : {
254+ workspace_id : 'ws_123' ,
255+ query_length : 4 ,
256+ result_count : 2 ,
257+ } ,
215258 } ,
216- } ) ;
259+ ) ;
217260
218- await flushInternalTelemetryBatchesForTests ( ) ;
219261 await Promise . all ( [ p1 , p2 ] ) ;
220262
221- expect ( fetchMock ) . toHaveBeenCalledTimes ( 1 ) ;
222- const [ url , init ] = fetchMock . mock . calls [ 0 ] as [ string , RequestInit ] ;
223- expect ( url ) . toBe ( 'https://us.i.posthog.com/batch/' ) ;
224- expect ( init . method ) . toBe ( 'POST' ) ;
225-
226- const payload = JSON . parse ( String ( init . body ) ) ;
227- expect ( Array . isArray ( payload . batch ) ) . toBe ( true ) ;
228- expect ( payload . batch ) . toHaveLength ( 2 ) ;
263+ // SDK handles batching internally — we just verify both events were captured
264+ expect ( mockCapture ) . toHaveBeenCalledTimes ( 2 ) ;
229265 } ) ;
230266} ) ;
0 commit comments