package mock import ( "bytes" "context" "encoding/csv" "encoding/json" "strings" "tera-clone/services/tera-api/internal/domain" "testing" ) func TestPortLogScopeAppliesBeforePaginationAndExport(t *testing.T) { s := NewStore(fixedClock) defer s.Close() s.portLogLoaded = true s.portLogEvents = []domain.PortLogEvent{{Channel: "CH01", Timestamp: fixedClock(), EventType: "session", Message: "private-one"}, {Channel: "CH18", Timestamp: fixedClock(), EventType: "session", Message: "allowed-eighteen"}} ctx := domain.WithActor(context.Background(), domain.Actor{Name: "operator", Role: "port_operator", PortAccess: map[string]string{"CH18": "read"}}) rows, err := s.PortLogEvents(ctx, domain.PortLogFilter{Limit: 1}) if err != nil || len(rows) != 1 || rows[0].Channel != "CH18" { t.Fatalf("scope/page: %#v %v", rows, err) } for _, format := range []string{"csv", "json", "jsonl"} { var out bytes.Buffer _, err := s.StreamLogExport(ctx, domain.LogExportRequest{LogType: "port", Format: format}, &out) if err != nil { t.Fatal(err) } if strings.Contains(out.String(), "private-one") || !strings.Contains(out.String(), "allowed-eighteen") { t.Fatalf("leaking export %s: %s", format, out.String()) } } } func TestCSVExportQuotesCellsAndBlocksSpreadsheetFormulas(t *testing.T) { var out bytes.Buffer rows := []any{map[string]string{"message": "=HYPERLINK(\"bad\")", "actor": "a,b\nc"}} if err := writeLogExport(&out, "csv", rows); err != nil { t.Fatal(err) } data, err := csv.NewReader(strings.NewReader(strings.TrimPrefix(out.String(), "\ufeff"))).ReadAll() if err != nil { t.Fatal(err) } if len(data) != 2 || data[1][0] != "a,b\nc" || !strings.HasPrefix(data[1][1], "'=HYPERLINK") { t.Fatalf("unsafe CSV: %#v", data) } out.Reset() if err := writeLogExport(&out, "json", rows); err != nil { t.Fatal(err) } var decoded []map[string]string if err := json.Unmarshal(out.Bytes(), &decoded); err != nil || len(decoded) != 1 { t.Fatal("invalid JSON export") } }