@@ -49,8 +49,8 @@ public void TearDown()
4949 [ Test ]
5050 public async Task SendBatchAsync_200_DeletesFilesFromDisk ( )
5151 {
52- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" a \" }" ) ;
53- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" b \" }" ) ;
52+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , "a" ) ) ) ;
53+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , "b" ) ) ) ;
5454
5555 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :2,\" { ResponseFields . Rejected } \" :0}}") ;
5656 using var transport = new HttpTransport ( _store , TestDefaults . PublishableKey , handler : handler ) ;
@@ -65,7 +65,7 @@ public async Task SendBatchAsync_200_DeletesFilesFromDisk()
6565 [ Test ]
6666 public async Task SendBatchAsync_200_SendsGzippedPayloadWithCorrectHeaders ( )
6767 {
68- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" test\" }" ) ;
68+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , " test" ) ) ) ;
6969
7070 byte [ ] ? capturedBody = null ;
7171 string ? capturedKey = null ;
@@ -75,7 +75,7 @@ public async Task SendBatchAsync_200_SendsGzippedPayloadWithCorrectHeaders()
7575 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :0}}",
7676 onRequest : req =>
7777 {
78- capturedKey = string . Join ( "" , req . Headers . GetValues ( "x-immutable-publishable-key" ) ) ;
78+ capturedKey = string . Join ( "" , req . Headers . GetValues ( Constants . PublishableKeyHeader ) ) ;
7979 capturedContentType = req . Content ! . Headers . ContentType ! . MediaType ;
8080 capturedContentEncoding = string . Join ( "" , req . Content . Headers . ContentEncoding ) ;
8181 capturedBody = req . Content . ReadAsByteArrayAsync ( ) . Result ;
@@ -91,13 +91,13 @@ public async Task SendBatchAsync_200_SendsGzippedPayloadWithCorrectHeaders()
9191 var decompressed = DecompressGzip ( capturedBody ! ) ;
9292 StringAssert . StartsWith ( $ "{{\" { ResponseFields . MessagesEnvelope } \" :[", decompressed ) ;
9393 StringAssert . EndsWith ( "]}" , decompressed ) ;
94- StringAssert . Contains ( "\" eventName \" :\" test\" " , decompressed ) ;
94+ StringAssert . Contains ( $ "\" { MessageFields . EventName } \" :\" test\" ", decompressed ) ;
9595 }
9696#else
9797 [ Test ]
9898 public async Task SendBatchAsync_200_SendsPlainJsonPayloadWithoutContentEncoding ( )
9999 {
100- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" test\" }" ) ;
100+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , " test" ) ) ) ;
101101
102102 string ? capturedKey = null ;
103103 string ? capturedContentType = null ;
@@ -106,7 +106,7 @@ public async Task SendBatchAsync_200_SendsPlainJsonPayloadWithoutContentEncoding
106106 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :0}}",
107107 onRequest : req =>
108108 {
109- capturedKey = string . Join ( "" , req . Headers . GetValues ( "x-immutable-publishable-key" ) ) ;
109+ capturedKey = string . Join ( "" , req . Headers . GetValues ( Constants . PublishableKeyHeader ) ) ;
110110 capturedContentType = req . Content ! . Headers . ContentType ! . MediaType ;
111111 capturedContentEncodingCount = req . Content . Headers . ContentEncoding . Count ;
112112 capturedBody = req . Content . ReadAsStringAsync ( ) . Result ;
@@ -120,14 +120,14 @@ public async Task SendBatchAsync_200_SendsPlainJsonPayloadWithoutContentEncoding
120120 Assert . AreEqual ( 0 , capturedContentEncodingCount , "no Content-Encoding header is permitted in v1" ) ;
121121 StringAssert . StartsWith ( $ "{{\" { ResponseFields . MessagesEnvelope } \" :[", capturedBody ) ;
122122 StringAssert . EndsWith ( "]}" , capturedBody ) ;
123- StringAssert . Contains ( "\" eventName \" :\" test\" " , capturedBody ) ;
123+ StringAssert . Contains ( $ "\" { MessageFields . EventName } \" :\" test\" ", capturedBody ) ;
124124 }
125125#endif
126126
127127 [ Test ]
128128 public async Task SendBatchAsync_200_UsesCorrectUrlForTestKey ( )
129129 {
130- _store . Write ( "{ \" type \" : \" track \" }" ) ;
130+ _store . Write ( WireFixture . Track ( ) ) ;
131131
132132 HttpRequestMessage ? captured = null ;
133133 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :0}}",
@@ -142,7 +142,7 @@ public async Task SendBatchAsync_200_UsesCorrectUrlForTestKey()
142142 [ Test ]
143143 public async Task SendBatchAsync_200_UsesCorrectUrlForProdKey ( )
144144 {
145- _store . Write ( "{ \" type \" : \" track \" }" ) ;
145+ _store . Write ( WireFixture . Track ( ) ) ;
146146
147147 HttpRequestMessage ? captured = null ;
148148 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :0}}",
@@ -157,7 +157,7 @@ public async Task SendBatchAsync_200_UsesCorrectUrlForProdKey()
157157 [ Test ]
158158 public async Task SendBatchAsync_BaseUrlOverride_WinsOverKeyPrefix ( )
159159 {
160- _store . Write ( "{ \" type \" : \" track \" }" ) ;
160+ _store . Write ( WireFixture . Track ( ) ) ;
161161
162162 HttpRequestMessage ? captured = null ;
163163 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :0}}",
@@ -188,7 +188,7 @@ public async Task SendBatchAsync_EmptyQueue_ReturnsFalse()
188188 [ Test ]
189189 public async Task SendBatchAsync_4xx_DeletesFilesAndResetsBackoff ( )
190190 {
191- _store . Write ( "{ \" type \" : \" track \" }" ) ;
191+ _store . Write ( WireFixture . Track ( ) ) ;
192192
193193 var handler = new MockHandler ( HttpStatusCode . BadRequest , "" ) ;
194194 AudienceError ? reportedError = null ;
@@ -206,7 +206,7 @@ public async Task SendBatchAsync_4xx_DeletesFilesAndResetsBackoff()
206206 [ Test ]
207207 public async Task SendBatchAsync_429_NoRetryAfter_KeepsFilesAndUsesExpoBackoff_NoError ( )
208208 {
209- _store . Write ( "{ \" type \" : \" track \" }" ) ;
209+ _store . Write ( WireFixture . Track ( ) ) ;
210210
211211 var handler = new MockHandler ( ( HttpStatusCode ) 429 , "" ) ;
212212 AudienceError ? reportedError = null ;
@@ -224,7 +224,7 @@ public async Task SendBatchAsync_429_NoRetryAfter_KeepsFilesAndUsesExpoBackoff_N
224224 [ Test ]
225225 public async Task SendBatchAsync_429_RetryAfterDeltaSeconds_OverridesExpoBackoff ( )
226226 {
227- _store . Write ( "{ \" type \" : \" track \" }" ) ;
227+ _store . Write ( WireFixture . Track ( ) ) ;
228228
229229 var handler = new MockHandler ( ( ) =>
230230 {
@@ -247,7 +247,7 @@ public async Task SendBatchAsync_429_RetryAfterHttpDate_OverridesExpoBackoff()
247247 // ParseRetryAfter computes the delta against DateTimeOffset.UtcNow,
248248 // which we can't pin from outside; assert only that a future date
249249 // engages the window. The seconds-form test above pins exact math.
250- _store . Write ( "{ \" type \" : \" track \" }" ) ;
250+ _store . Write ( WireFixture . Track ( ) ) ;
251251
252252 var handler = new MockHandler ( ( ) =>
253253 {
@@ -269,7 +269,7 @@ public async Task SendBatchAsync_429_PastRetryAfterDate_FallsBackToExpoBackoff()
269269 {
270270 // Past Retry-After (clock skew or server bug) must not let
271271 // IsInBackoffWindow flip false and trigger instant retry.
272- _store . Write ( "{ \" type \" : \" track \" }" ) ;
272+ _store . Write ( WireFixture . Track ( ) ) ;
273273
274274 var handler = new MockHandler ( ( ) =>
275275 {
@@ -289,7 +289,7 @@ public async Task SendBatchAsync_429_PastRetryAfterDate_FallsBackToExpoBackoff()
289289 [ Test ]
290290 public async Task SendBatchAsync_429ThenSuccess_DeliversBatchAndClearsBackoff ( )
291291 {
292- _store . Write ( "{ \" type \" : \" track \" }" ) ;
292+ _store . Write ( WireFixture . Track ( ) ) ;
293293
294294 var callCount = 0 ;
295295 var handler = new MockHandler ( ( ) =>
@@ -322,8 +322,8 @@ public async Task SendBatchAsync_200_WithRejected_DeletesFilesAndSurfacesValidat
322322 // per-message validation errors. The batch is deleted (retries
323323 // would not help) and the count is surfaced via onError so
324324 // studios can observe silently dropped events.
325- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" a \" }" ) ;
326- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" b \" }" ) ;
325+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , "a" ) ) ) ;
326+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , "b" ) ) ) ;
327327
328328 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :1}}") ;
329329 AudienceError ? reportedError = null ;
@@ -341,7 +341,7 @@ public async Task SendBatchAsync_200_WithRejected_DeletesFilesAndSurfacesValidat
341341 [ Test ]
342342 public async Task SendBatchAsync_200_ZeroRejected_DoesNotFireOnError ( )
343343 {
344- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" a \" }" ) ;
344+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , "a" ) ) ) ;
345345
346346 var handler = new MockHandler ( HttpStatusCode . OK , $ "{{\" accepted\" :1,\" { ResponseFields . Rejected } \" :0}}") ;
347347 AudienceError ? reportedError = null ;
@@ -357,7 +357,7 @@ public async Task SendBatchAsync_200_ZeroRejected_DoesNotFireOnError()
357357 public async Task SendBatchAsync_200_MalformedBody_TreatsAsZeroRejected ( )
358358 {
359359 // Malformed diagnostic body must not block the success path.
360- _store . Write ( "{ \" type \" : \" track \" , \" eventName \" : \" a \" }" ) ;
360+ _store . Write ( WireFixture . Track ( ( MessageFields . EventName , "a" ) ) ) ;
361361
362362 var handler = new MockHandler ( HttpStatusCode . OK , "not-json" ) ;
363363 AudienceError ? reportedError = null ;
@@ -373,7 +373,7 @@ public async Task SendBatchAsync_200_MalformedBody_TreatsAsZeroRejected()
373373 [ Test ]
374374 public async Task SendBatchAsync_5xx_KeepsFilesAndIncreasesBackoff ( )
375375 {
376- _store . Write ( "{ \" type \" : \" track \" }" ) ;
376+ _store . Write ( WireFixture . Track ( ) ) ;
377377
378378 var handler = new MockHandler ( HttpStatusCode . InternalServerError , "" ) ;
379379 AudienceError ? reportedError = null ;
@@ -392,7 +392,7 @@ public async Task SendBatchAsync_5xx_KeepsFilesAndIncreasesBackoff()
392392 [ Test ]
393393 public async Task BackoffMs_EscalatesOnlyAfterWindowElapsed ( )
394394 {
395- _store . Write ( "{ \" type \" : \" track \" }" ) ;
395+ _store . Write ( WireFixture . Track ( ) ) ;
396396 var handler = new MockHandler ( HttpStatusCode . InternalServerError , "" ) ;
397397 using var transport = new HttpTransport ( _store , TestDefaults . PublishableKey ,
398398 handler : handler , getUtcNow : _getUtcNow ) ;
@@ -426,7 +426,7 @@ public async Task BackoffMs_EscalatesOnlyAfterWindowElapsed()
426426 [ Test ]
427427 public async Task BackoffMs_DoesNotEscalateWhileInsidePreviousWindow ( )
428428 {
429- _store . Write ( "{ \" type \" : \" track \" }" ) ;
429+ _store . Write ( WireFixture . Track ( ) ) ;
430430 var handler = new MockHandler ( HttpStatusCode . InternalServerError , "" ) ;
431431 using var transport = new HttpTransport ( _store , TestDefaults . PublishableKey ,
432432 handler : handler , getUtcNow : _getUtcNow ) ;
@@ -458,7 +458,7 @@ public async Task BackoffMs_DoesNotEscalateWhileInsidePreviousWindow()
458458 [ Test ]
459459 public async Task BackoffMs_ResetsAfterSuccess ( )
460460 {
461- _store . Write ( "{ \" type \" : \" track \" }" ) ;
461+ _store . Write ( WireFixture . Track ( ) ) ;
462462
463463 var callCount = 0 ;
464464 var handler = new MockHandler ( ( ) =>
@@ -489,7 +489,7 @@ public async Task BackoffMs_ResetsAfterSuccess()
489489 [ Test ]
490490 public async Task SendBatchAsync_NetworkError_KeepsFilesAndBacksOff ( )
491491 {
492- _store . Write ( "{ \" type \" : \" track \" }" ) ;
492+ _store . Write ( WireFixture . Track ( ) ) ;
493493
494494 var handler = new MockHandler ( ( ) => throw new HttpRequestException ( "connection refused" ) ) ;
495495 AudienceError ? reportedError = null ;
@@ -512,7 +512,7 @@ public async Task SendBatchAsync_HttpClientTimeout_TreatedAsNetworkError()
512512 // guard, timeouts would be silently swallowed as "shutdown": no backoff, no error
513513 // callback, next cycle hot-loops. This test ensures timeouts flow through the
514514 // NetworkError path.
515- _store . Write ( "{ \" type \" : \" track \" }" ) ;
515+ _store . Write ( WireFixture . Track ( ) ) ;
516516
517517 var handler = new MockHandler ( ( ) => throw new TaskCanceledException ( "Request timed out" ) ) ;
518518 AudienceError ? reportedError = null ;
@@ -538,7 +538,7 @@ public async Task SendBatchAsync_CallerCancelled_Throws_DoesNotDeleteOrRecordFai
538538 // with the batch still on disk, and a FlushAsync loop watching
539539 // that return value would re-enter on the same cancelled token
540540 // forever: nothing ever drains, nothing ever throws.
541- _store . Write ( "{ \" type \" : \" track \" }" ) ;
541+ _store . Write ( WireFixture . Track ( ) ) ;
542542
543543 var handler = new MockHandler ( ( ) => throw new OperationCanceledException ( "simulated" ) ) ;
544544 AudienceError ? reportedError = null ;
@@ -570,7 +570,7 @@ public async Task SendBatchAsync_CallerCancelled_Throws_DoesNotDeleteOrRecordFai
570570 [ Test ]
571571 public async Task IsInBackoffWindow_ClearsAfterNextAttemptAtElapses ( )
572572 {
573- _store . Write ( "{ \" type \" : \" track \" }" ) ;
573+ _store . Write ( WireFixture . Track ( ) ) ;
574574
575575 var now = new DateTime ( 2026 , 4 , 17 , 12 , 0 , 0 , DateTimeKind . Utc ) ;
576576 var handler = new MockHandler ( HttpStatusCode . InternalServerError , "" ) ;
@@ -594,7 +594,7 @@ public async Task IsInBackoffWindow_ClearsAfterNextAttemptAtElapses()
594594 [ Test ]
595595 public async Task SendBatchAsync_ErrorCallbackThrows_DoesNotCrash ( )
596596 {
597- _store . Write ( "{ \" type \" : \" track \" }" ) ;
597+ _store . Write ( WireFixture . Track ( ) ) ;
598598
599599 var handler = new MockHandler ( HttpStatusCode . BadRequest , "" ) ;
600600 using var transport = new HttpTransport ( _store , TestDefaults . PublishableKey ,
0 commit comments