Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pengen beli BMW tapi kok mahal ya :) #25

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 268 additions & 0 deletions business/payment_service/get_details_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
package payment_service_test

import (
"context"
"database/sql"
"errors"
"mock-payment-provider/business"
"mock-payment-provider/business/payment_service"
"mock-payment-provider/primitive"
"mock-payment-provider/repository"
"mock-payment-provider/repository/emoney"
"mock-payment-provider/repository/transaction"
"mock-payment-provider/repository/virtual_account"
"mock-payment-provider/repository/webhook"
"os"
"testing"
"time"

"log"

_ "github.com/mattn/go-sqlite3"
)

var (
db *sql.DB
cfg config
)

func TestMain(m *testing.M) {
var err error = nil

cfg = parseConfig()
db, err = sql.Open("sqlite3", cfg.databasePath)
if err != nil {
log.Fatalf("Opening sql database: %s", err.Error())
}

db.SetMaxOpenConns(1)

setupCtx, setupCancel := context.WithTimeout(context.Background(), time.Minute*5)
defer setupCancel()

transactionRepository, err := transaction.NewTransactionRepository(db)
if err != nil {
log.Fatalf("Creating transaction repository: %s", err.Error())
}
err = transactionRepository.Migrate(setupCtx)
if err != nil {
log.Fatalf("migrating transaction repository: %s", err.Error())
}

virtualAccountRepository, err := virtual_account.NewVirtualAccountRepository(db)
if err != nil {
log.Fatalf("Creating virtual account repository: %s", err.Error())
}
err = virtualAccountRepository.Migrate(setupCtx)
if err != nil {
log.Fatalf("migrating virtual account repository: %s", err.Error())
}

emoneyRepository, err := emoney.NewEmoneyRepository(db)
if err != nil {
log.Fatalf("Creating emoney repository: %s", err.Error())
}
err = emoneyRepository.Migrate(setupCtx)
if err != nil {
log.Fatalf("migrating emoney repository: %s", err.Error())
}

exitCode := m.Run()

_, err = db.Exec("DELETE FROM transaction_log")
if err != nil {
log.Printf("DELETE transaction log: %s", err.Error())
}
_, err = db.Exec("DELETE FROM virtual_accounts")
if err != nil {
log.Printf("DELETE virtual accounts: %s", err.Error())
}
_, err = db.Exec("DELETE FROM virtual_account_entries")
if err != nil {
log.Printf("DELETE virtual account entries: %s", err.Error())
}
_, err = db.Exec("DELETE FROM emoney_entries")
if err != nil {
log.Printf("DELETE FROM emoney entries: %s", err.Error())
}
err = db.Close()
if err != nil {
log.Printf("Closing database: %s", err.Error())
}

os.Exit(exitCode)
}

type config struct {
httpHostname string
httpPort string
databasePath string
webhookTargetURL string
serverKey string
}

func defaultConfig() config {
return config{
httpHostname: "localhost",
httpPort: "3000",
databasePath: "payment.db",
}
}

func parseConfig() config {
result := defaultConfig()

if v, ok := os.LookupEnv("HTTP_HOSTNAME"); ok {
result.httpHostname = v
}

if v, ok := os.LookupEnv("HTTP_PORT"); ok {
result.httpPort = v
}

if v, ok := os.LookupEnv("DATABASE_PATH"); ok {
result.databasePath = v
}

if v, ok := os.LookupEnv("WEBHOOK_TARGET_URL"); ok {
result.webhookTargetURL = v
}

if v, ok := os.LookupEnv("SERVER_KEY"); ok {
result.serverKey = v
}

return result
}

func TestBusinessGetDetails(t *testing.T) {

ctx, setupCancel := context.WithTimeout(context.Background(), time.Minute*5)
defer setupCancel()
transactionRepository, err := transaction.NewTransactionRepository(db)
if err != nil {
t.Errorf("creating transaction repository: %s", err.Error())
}
virtualAccountRepository, err := virtual_account.NewVirtualAccountRepository(db)
if err != nil {
t.Errorf("creating virtual account repository: %s", err.Error())
}

emoneyRepository, err := emoney.NewEmoneyRepository(db)
if err != nil {
t.Errorf("creating emoney repository: %s", err.Error())
}
webhookClient, err := webhook.NewWebhookClient(cfg.webhookTargetURL)
if err != nil {
t.Errorf("creating webhook client: %s", err.Error())
}

paymentService, err := payment_service.NewPaymentService(payment_service.Config{
ServerKey: cfg.serverKey,
TransactionRepository: transactionRepository,
EMoneyRepository: emoneyRepository,
WebhookClient: webhookClient,
VirtualAccountRepository: virtualAccountRepository,
})
if err != nil {
t.Fatalf("creating payment service: %s", err.Error())
}

t.Run("GetDetails should return not found if the order id is empty", func(t *testing.T) {
runGetDetailsShouldReturnNotFoundIfTheOrderIdIsEmpty(ctx, t, paymentService)
})
t.Run("GetDetails should return err 'not found' if the order id is not found", func(t *testing.T) {
runGetDetailsShouldReturnErrorNotFoundIfTheOrderIdIsNotFound(ctx, t, paymentService)
})

t.Run("GetDetails should return the correct details", func(t *testing.T) {
runGetDetailsShouldReturnTheCorrectDetails(ctx, t, virtualAccountRepository, emoneyRepository, paymentService, transactionRepository)
})

}

// GetDetails should return not found if the order id is empty
func runGetDetailsShouldReturnNotFoundIfTheOrderIdIsEmpty(ctx context.Context, t *testing.T, paymentService *payment_service.Dependency) {
_, err := paymentService.GetDetail(ctx, "")
if err == nil {
t.Error("expecting error to be not nil, but got nil")
}
if err.Error() != "acquiring from virtual account store: virtualAccountNumber is empty" {
t.Errorf("expecting error %s, instead got %v", business.ErrTransactionNotFound, err)
}
}

// GetDetails should return err 'not found' if the order id is not found
func runGetDetailsShouldReturnErrorNotFoundIfTheOrderIdIsNotFound(ctx context.Context, t *testing.T, paymentService *payment_service.Dependency) {
_, err := paymentService.GetDetail(ctx, "not-exist")
if err == nil {
t.Error("expecting error to be not nil, but got nil")
}
if !errors.Is(err, business.ErrTransactionNotFound) {
t.Errorf("expecting error %s, instead got %v", business.ErrTransactionNotFound, err)
}
}

// GetDetails should return the correct details]
func runGetDetailsShouldReturnTheCorrectDetails(ctx context.Context, t *testing.T, virtualAccountRepository *virtual_account.Repository, emoneyRepository *emoney.Repository, paymentService *payment_service.Dependency, transactionRepository *transaction.Repository) {
vaNumber, err := virtualAccountRepository.CreateOrGetVirtualAccountNumber(ctx, "[email protected]")
if err != nil {
t.Errorf("unexpected error: %s", err.Error())
}

orderId := "order-id"
id, err := virtualAccountRepository.CreateCharge(ctx, vaNumber, orderId, 50000, time.Now().Add(time.Hour))
if err != nil {
t.Errorf("unexpected error: %s", err.Error())
}
if id == "" {
t.Error("expecting id to be not empty")
}

createCharge, err := emoneyRepository.CreateCharge(ctx, orderId, 50000, time.Now().Add(time.Hour))
if err != nil {
t.Errorf("unexpected error: %s", err.Error())
}
if createCharge == "" {
t.Error("expecting createCharge to be not empty")
}

_, err = paymentService.GetDetail(ctx, vaNumber)
if err == nil {
t.Error("expecting error to be not nil, but got nil")
}
if !errors.Is(err, business.ErrTransactionNotFound) {
t.Errorf("expecting error %s, instead got %v", business.ErrTransactionNotFound, err)
}

err = transactionRepository.Create(ctx, repository.CreateTransactionParam{
OrderID: orderId,
Amount: 50000,
PaymentType: primitive.PaymentTypeEMoneyQRIS,
Status: primitive.TransactionStatusPending,
ExpiredAt: time.Now().Add(time.Hour),
})
if err != nil {
t.Errorf("expecting not error when inserting transaction, instead got %s", err.Error())
}

details, err := paymentService.GetDetail(ctx, vaNumber)
if err != nil {
t.Errorf("unexpected error: %s", err.Error())
}
if details.OrderId != orderId {
t.Errorf("expecting orderId to be %s, instead got %s", orderId, details.OrderId)
}
if details.ChargedAmount != 50000 {
t.Errorf("expecting charged amount to be 50000 instead got %d", details.ChargedAmount)
}
if details.Status != primitive.TransactionStatusPending {
t.Errorf("expecting status to be %s, instead got %s", primitive.TransactionStatusPending, details.Status)
}
if details.PaymentMethod != primitive.PaymentTypeEMoneyQRIS {
t.Errorf("expecting payment type to be %s, instead got %s", primitive.PaymentTypeEMoneyQRIS, details.PaymentMethod)
}
if details.VirtualAccountNumber != vaNumber {
t.Errorf("expecting virtual account number to be %s, instead got %s", vaNumber, details.VirtualAccountNumber)
}
}
Loading
Loading