110 lines
3.6 KiB
Go
110 lines
3.6 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"oci-portal/internal/oci"
|
|
)
|
|
|
|
// billingStubClient 只桩账单方法,其余经内嵌 fakeClient 兜底。
|
|
type billingStubClient struct {
|
|
*fakeClient
|
|
|
|
invoices []oci.Invoice
|
|
lines []oci.InvoiceLine
|
|
methods []oci.PaymentMethod
|
|
pdf []byte
|
|
|
|
listYear int
|
|
paidID string
|
|
paidEmail string
|
|
}
|
|
|
|
func (f *billingStubClient) ListInvoices(ctx context.Context, cred oci.Credentials, year int) ([]oci.Invoice, error) {
|
|
f.listYear = year
|
|
return f.invoices, nil
|
|
}
|
|
|
|
func (f *billingStubClient) ListInvoiceLines(ctx context.Context, cred oci.Credentials, internalInvoiceID string) ([]oci.InvoiceLine, error) {
|
|
return f.lines, nil
|
|
}
|
|
|
|
func (f *billingStubClient) DownloadInvoicePdf(ctx context.Context, cred oci.Credentials, internalInvoiceID string, maxBytes int64) ([]byte, error) {
|
|
return f.pdf, nil
|
|
}
|
|
|
|
func (f *billingStubClient) PayInvoice(ctx context.Context, cred oci.Credentials, internalInvoiceID, email string) error {
|
|
f.paidID, f.paidEmail = internalInvoiceID, email
|
|
return nil
|
|
}
|
|
|
|
func (f *billingStubClient) ListPaymentMethods(ctx context.Context, cred oci.Credentials) ([]oci.PaymentMethod, error) {
|
|
return f.methods, nil
|
|
}
|
|
|
|
func TestInvoicesAndPaymentMethods(t *testing.T) {
|
|
client := &billingStubClient{
|
|
fakeClient: &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}},
|
|
invoices: []oci.Invoice{{ID: "inv1", Number: "100001", Status: "OPEN"}},
|
|
lines: []oci.InvoiceLine{{Product: "Compute", Total: 12.5}},
|
|
methods: []oci.PaymentMethod{{Method: "CREDIT_CARD", LastDigits: "4242"}},
|
|
pdf: []byte("%PDF-1.4 fake"),
|
|
}
|
|
svc := newTestService(t, client)
|
|
cfg := importAliveConfig(t, svc)
|
|
ctx := context.Background()
|
|
|
|
if list, err := svc.Invoices(ctx, cfg.ID, 0); err != nil || len(list) != 1 || list[0].Number != "100001" {
|
|
t.Fatalf("Invoices = %v, %v", list, err)
|
|
}
|
|
if _, err := svc.Invoices(ctx, cfg.ID, 2026); err != nil || client.listYear != 2026 {
|
|
t.Fatalf("Invoices(year) 透传 = %d, %v, want 2026", client.listYear, err)
|
|
}
|
|
if _, err := svc.Invoices(ctx, cfg.ID, 26); err == nil {
|
|
t.Fatal("Invoices(26) 应拒绝非法年份")
|
|
}
|
|
if lines, err := svc.InvoiceLines(ctx, cfg.ID, "6100"); err != nil || len(lines) != 1 {
|
|
t.Fatalf("InvoiceLines = %v, %v", lines, err)
|
|
}
|
|
if data, err := svc.InvoicePdf(ctx, cfg.ID, "6100"); err != nil || len(data) == 0 {
|
|
t.Fatalf("InvoicePdf = %d bytes, %v", len(data), err)
|
|
}
|
|
if ms, err := svc.PaymentMethods(ctx, cfg.ID); err != nil || len(ms) != 1 || ms[0].LastDigits != "4242" {
|
|
t.Fatalf("PaymentMethods = %v, %v", ms, err)
|
|
}
|
|
}
|
|
|
|
func TestPayInvoiceValidation(t *testing.T) {
|
|
client := &billingStubClient{fakeClient: &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}}}
|
|
svc := newTestService(t, client)
|
|
cfg := importAliveConfig(t, svc)
|
|
ctx := context.Background()
|
|
|
|
tests := []struct {
|
|
name, internalID, email, wantErr string
|
|
}{
|
|
{"内部 ID 为空", "", "a@b.c", "internal invoice id is empty"},
|
|
{"邮箱非法", "6100", "not-an-email", "invalid receipt email"},
|
|
{"合法请求", "6100", "billing@example.com", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := svc.PayInvoice(ctx, cfg.ID, tt.internalID, tt.email)
|
|
if tt.wantErr == "" {
|
|
if err != nil {
|
|
t.Fatalf("err = %v, want nil", err)
|
|
}
|
|
if client.paidID != tt.internalID || client.paidEmail != tt.email {
|
|
t.Fatalf("透传 = (%s, %s), want (%s, %s)", client.paidID, client.paidEmail, tt.internalID, tt.email)
|
|
}
|
|
return
|
|
}
|
|
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
|
|
t.Fatalf("err = %v, want contains %q", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|