44 "bytes"
55 "context"
66 "encoding/json"
7+ "fmt"
78 "io"
89 "os"
910 "testing"
@@ -34,8 +35,9 @@ func captureStdout(t *testing.T, fn func()) string {
3435}
3536
3637type FakeBrowserTelemetryService struct {
37- StreamFunc func () * ssestream.Stream [kernel.BrowserTelemetryStreamResponse ]
38- EventsFunc func (ctx context.Context , id string , query kernel.BrowserTelemetryEventsParams , opts ... option.RequestOption ) (* pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ], error )
38+ StreamFunc func () * ssestream.Stream [kernel.BrowserTelemetryStreamResponse ]
39+ EventsFunc func (ctx context.Context , id string , query kernel.BrowserTelemetryEventsParams , opts ... option.RequestOption ) (* pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ], error )
40+ EventsAutoPagingFunc func () * pagination.OffsetPaginationAutoPager [kernel.BrowserTelemetryEventsResponse ]
3941}
4042
4143func (f * FakeBrowserTelemetryService ) StreamStreaming (ctx context.Context , id string , query kernel.BrowserTelemetryStreamParams , opts ... option.RequestOption ) * ssestream.Stream [kernel.BrowserTelemetryStreamResponse ] {
@@ -52,6 +54,13 @@ func (f *FakeBrowserTelemetryService) Events(ctx context.Context, id string, que
5254 return & pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ]{}, nil
5355}
5456
57+ func (f * FakeBrowserTelemetryService ) EventsAutoPaging (ctx context.Context , id string , query kernel.BrowserTelemetryEventsParams , opts ... option.RequestOption ) * pagination.OffsetPaginationAutoPager [kernel.BrowserTelemetryEventsResponse ] {
58+ if f .EventsAutoPagingFunc != nil {
59+ return f .EventsAutoPagingFunc ()
60+ }
61+ return pagination .NewOffsetPaginationAutoPager (& pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ]{}, nil )
62+ }
63+
5564func TestTelemetryStream_NilTelemetryErrors (t * testing.T ) {
5665 b := BrowsersCmd {browsers : & FakeBrowsersService {}}
5766
@@ -425,3 +434,100 @@ func TestTelemetryEvents_OffsetIgnoresSinceKeepsUntil(t *testing.T) {
425434 assert .NoError (t , err )
426435 _ = buf
427436}
437+
438+ func TestTelemetryEvents_UnknownCategoryErrors (t * testing.T ) {
439+ b := BrowsersCmd {browsers : & FakeBrowsersService {}, telemetry : & FakeBrowserTelemetryService {}}
440+
441+ err := b .TelemetryEvents (context .Background (), BrowsersTelemetryEventsInput {Identifier : "br-1" , Categories : []string {"netowrk" }})
442+
443+ assert .Error (t , err )
444+ assert .Contains (t , err .Error (), "invalid --categories value" )
445+ }
446+
447+ func TestTelemetryEvents_InvalidLimitErrors (t * testing.T ) {
448+ b := BrowsersCmd {browsers : & FakeBrowsersService {}, telemetry : & FakeBrowserTelemetryService {}}
449+
450+ for _ , lim := range []int64 {- 1 , 101 } {
451+ err := b .TelemetryEvents (context .Background (), BrowsersTelemetryEventsInput {Identifier : "br-1" , Limit : lim })
452+ assert .Error (t , err )
453+ assert .Contains (t , err .Error (), "invalid --limit value" )
454+ }
455+ }
456+
457+ // Categories are filtered server-side, but the SDK comma-joins a []string field
458+ // into one value the endpoint won't match, so they go out as repeated query
459+ // params instead of the typed Category field.
460+ func TestTelemetryEvents_CategoriesSentAsRepeatedQueryParams (t * testing.T ) {
461+ buf := capturePtermOutput (t )
462+ fakeBrowsers := & FakeBrowsersService {GetFunc : func (ctx context.Context , id string , query kernel.BrowserGetParams , opts ... option.RequestOption ) (* kernel.BrowserGetResponse , error ) {
463+ return & kernel.BrowserGetResponse {SessionID : "sess-1" }, nil
464+ }}
465+ var gotQuery kernel.BrowserTelemetryEventsParams
466+ var gotOpts []option.RequestOption
467+ fakeTelemetry := & FakeBrowserTelemetryService {
468+ EventsFunc : func (ctx context.Context , id string , query kernel.BrowserTelemetryEventsParams , opts ... option.RequestOption ) (* pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ], error ) {
469+ gotQuery , gotOpts = query , opts
470+ return & pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ]{}, nil
471+ },
472+ }
473+ b := BrowsersCmd {browsers : fakeBrowsers , telemetry : fakeTelemetry }
474+
475+ err := b .TelemetryEvents (context .Background (), BrowsersTelemetryEventsInput {Identifier : "br-1" , Categories : []string {"console" , "network" }})
476+
477+ assert .NoError (t , err )
478+ assert .Empty (t , gotQuery .Category , "categories must not use the comma-joined typed field" )
479+ // Two category query params plus the response-capture option for the cursor.
480+ assert .Len (t , gotOpts , 3 )
481+ _ = buf
482+ }
483+
484+ // The events archive outlives the session, so a 404 from Get (e.g. an ended
485+ // session) must not stop the read: the command falls back to the raw identifier.
486+ func TestTelemetryEvents_FallsBackToIdentifierWhenGetFails (t * testing.T ) {
487+ buf := capturePtermOutput (t )
488+ fakeBrowsers := & FakeBrowsersService {GetFunc : func (ctx context.Context , id string , query kernel.BrowserGetParams , opts ... option.RequestOption ) (* kernel.BrowserGetResponse , error ) {
489+ return nil , fmt .Errorf ("not found" )
490+ }}
491+ var gotID string
492+ fakeTelemetry := & FakeBrowserTelemetryService {
493+ EventsFunc : func (ctx context.Context , id string , query kernel.BrowserTelemetryEventsParams , opts ... option.RequestOption ) (* pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ], error ) {
494+ gotID = id
495+ return & pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ]{}, nil
496+ },
497+ }
498+ b := BrowsersCmd {browsers : fakeBrowsers , telemetry : fakeTelemetry }
499+
500+ err := b .TelemetryEvents (context .Background (), BrowsersTelemetryEventsInput {Identifier : "ended-session-id" })
501+
502+ assert .NoError (t , err )
503+ assert .Equal (t , "ended-session-id" , gotID )
504+ _ = buf
505+ }
506+
507+ // A --types filter is client-side, so it must scan every page in the window to be
508+ // complete. Setting --types (without --all) must therefore route through the
509+ // auto-pager, not the single-page fetch that could drop matches on later pages.
510+ func TestTelemetryEvents_TypesFilterWalksAllPages (t * testing.T ) {
511+ buf := capturePtermOutput (t )
512+ fakeBrowsers := & FakeBrowsersService {GetFunc : func (ctx context.Context , id string , query kernel.BrowserGetParams , opts ... option.RequestOption ) (* kernel.BrowserGetResponse , error ) {
513+ return & kernel.BrowserGetResponse {SessionID : "sess-1" }, nil
514+ }}
515+ autoPaged := false
516+ fakeTelemetry := & FakeBrowserTelemetryService {
517+ EventsFunc : func (ctx context.Context , id string , query kernel.BrowserTelemetryEventsParams , opts ... option.RequestOption ) (* pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ], error ) {
518+ t .Fatalf ("single-page Events must not be called when --types is set" )
519+ return nil , nil
520+ },
521+ EventsAutoPagingFunc : func () * pagination.OffsetPaginationAutoPager [kernel.BrowserTelemetryEventsResponse ] {
522+ autoPaged = true
523+ return pagination .NewOffsetPaginationAutoPager (& pagination.OffsetPagination [kernel.BrowserTelemetryEventsResponse ]{}, nil )
524+ },
525+ }
526+ b := BrowsersCmd {browsers : fakeBrowsers , telemetry : fakeTelemetry }
527+
528+ err := b .TelemetryEvents (context .Background (), BrowsersTelemetryEventsInput {Identifier : "br-1" , Types : []string {"network_response" }})
529+
530+ assert .NoError (t , err )
531+ assert .True (t , autoPaged , "--types must walk every page so the client-side filter is complete" )
532+ _ = buf
533+ }
0 commit comments