package analytics import ( "reflect" "strings" "testing" ) func TestPeerComparisonSupported(t *testing.T) { t.Parallel() if peerComparisonSupported("T318") { t.Fatal("peerComparisonSupported() = true for terminal scope") } if !peerComparisonSupported("") { t.Fatal("peerComparisonSupported() = false for merchant scope") } } func TestPaymentHistoryQueryUsesHoursForDay(t *testing.T) { t.Parallel() query, capacity := paymentHistoryQuery("DAY") if !strings.Contains(query, "local_hour") || !strings.Contains(query, "EXTRACT(HOUR") { t.Fatalf("paymentHistoryQuery(DAY) does not group by local hour:\n%s", query) } if capacity != 24 { t.Fatalf("paymentHistoryQuery(DAY) capacity = %d, want 24", capacity) } } func TestPaymentHistoryQueryKeepsDatesForLongerPeriods(t *testing.T) { t.Parallel() query, capacity := paymentHistoryQuery("WEEK") if strings.Contains(query, "EXTRACT(HOUR") { t.Fatalf("paymentHistoryQuery(WEEK) unexpectedly groups by hour:\n%s", query) } if capacity != 93 { t.Fatalf("paymentHistoryQuery(WEEK) capacity = %d, want 93", capacity) } } func TestTransactionStatusDistributionUsesCanonicalOrderAndShares(t *testing.T) { t.Parallel() metrics := metricValues{total: 20, unverified: 3, verified: 12, failed: 4, reversed: 1} got := transactionStatusDistribution(metrics) want := []TransactionStatusDistribution{ {Status: "Paid", Count: 3, SharePercent: stringPointer("15.00")}, {Status: "Verified", Count: 12, SharePercent: stringPointer("60.00")}, {Status: "Failed", Count: 4, SharePercent: stringPointer("20.00")}, {Status: "Reversed", Count: 1, SharePercent: stringPointer("5.00")}, } if !reflect.DeepEqual(got, want) { t.Fatalf("transactionStatusDistribution() = %#v, want %#v", got, want) } } func TestTransactionStatusDistributionHasUnavailableSharesWithoutSessions(t *testing.T) { t.Parallel() for _, item := range transactionStatusDistribution(metricValues{}) { if item.SharePercent != nil { t.Fatalf("share for %s = %q, want nil", item.Status, *item.SharePercent) } } } func TestStatusTrendQueryUsesReportingGranularity(t *testing.T) { t.Parallel() tests := []struct { name string periodType string wantStep string wantBucket string capacity int }{ {name: "day uses hours", periodType: "DAY", wantStep: "interval '1 hour'", wantBucket: "date_trunc('hour'", capacity: 24}, {name: "week uses days", periodType: "WEEK", wantStep: "interval '1 day'", wantBucket: "date_trunc('day'", capacity: 7}, {name: "month uses days", periodType: "JALALI_MONTH", wantStep: "interval '1 day'", wantBucket: "date_trunc('day'", capacity: 31}, {name: "season uses iranian weeks", periodType: "PERSIAN_SEASON", wantStep: "interval '7 days'", wantBucket: "interval '2 days'", capacity: 15}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { query, capacity := statusTrendQuery(tt.periodType) if !strings.Contains(query, tt.wantStep) || !strings.Contains(query, tt.wantBucket) { t.Fatalf("statusTrendQuery(%s) has unexpected granularity:\n%s", tt.periodType, query) } if capacity != tt.capacity { t.Fatalf("statusTrendQuery(%s) capacity = %d, want %d", tt.periodType, capacity, tt.capacity) } }) } } func stringPointer(value string) *string { return &value }