70 lines
2.9 KiB
Go
70 lines
2.9 KiB
Go
package processor
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/stretchr/testify/assert"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
|
||
|
|
"apskel-pos-be/internal/constants"
|
||
|
|
"apskel-pos-be/internal/models"
|
||
|
|
"apskel-pos-be/internal/repository"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Plays against Postgres, so the game repositories really join the transaction: a
|
||
|
|
// refused play leaves no game_plays row and no GAME_SPEND.
|
||
|
|
func TestPlayGame_AgainstPostgres(t *testing.T) {
|
||
|
|
db, _, player, _ := walletMoveDB(t)
|
||
|
|
gameID, prizeID := uuid.New(), uuid.New()
|
||
|
|
require.NoError(t, db.Exec(`INSERT INTO games (id, name, type, metadata) VALUES (?, 'Raffle', 'RAFFLE', '{"coin_cost": 2}')`, gameID).Error)
|
||
|
|
require.NoError(t, db.Exec(`INSERT INTO game_prizes (id, game_id, name, weight, stock) VALUES (?, ?, 'Tumbler', 1, 1)`, prizeID, gameID).Error)
|
||
|
|
t.Cleanup(func() {
|
||
|
|
db.Exec(`DELETE FROM wallet_lot_allocations WHERE transaction_id IN (SELECT id FROM wallet_transactions WHERE customer_id = ?)`, player)
|
||
|
|
db.Exec(`DELETE FROM game_plays WHERE game_id = ?`, gameID)
|
||
|
|
db.Exec(`DELETE FROM game_prizes WHERE game_id = ?`, gameID)
|
||
|
|
db.Exec(`DELETE FROM games WHERE id = ?`, gameID)
|
||
|
|
})
|
||
|
|
|
||
|
|
wallet := NewWalletProcessor(repository.NewWalletRepository(db))
|
||
|
|
txm := repository.NewTxManager(db)
|
||
|
|
require.NoError(t, txm.WithTransaction(context.Background(), func(ctx context.Context) error {
|
||
|
|
in := earn(player, 3, nil)
|
||
|
|
in.Currency = constants.WalletCurrencyCoin
|
||
|
|
_, err := wallet.Credit(ctx, in)
|
||
|
|
return err
|
||
|
|
}))
|
||
|
|
p := NewGamePlayProcessor(repository.NewGamePlayRepository(db), repository.NewGameRepository(db), repository.NewGamePrizeRepository(db),
|
||
|
|
wallet, repository.NewWalletQueryRepository(db), txm)
|
||
|
|
play := func() (*models.PlayGameResponse, error) {
|
||
|
|
return p.PlayGame(context.Background(), &models.PlayGameRequest{GameID: gameID, CustomerID: player})
|
||
|
|
}
|
||
|
|
|
||
|
|
res, err := play()
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Equal(t, int64(1), res.CoinsRemaining)
|
||
|
|
assert.Equal(t, 2, res.GamePlay.CoinsUsed)
|
||
|
|
|
||
|
|
var spend struct {
|
||
|
|
ReferenceID uuid.UUID
|
||
|
|
Amount int64
|
||
|
|
}
|
||
|
|
require.NoError(t, db.Raw(`SELECT reference_id, amount FROM wallet_transactions WHERE customer_id = ? AND type = 'GAME_SPEND'`, player).Scan(&spend).Error)
|
||
|
|
assert.Equal(t, res.GamePlay.ID, spend.ReferenceID)
|
||
|
|
assert.Equal(t, int64(-2), spend.Amount)
|
||
|
|
|
||
|
|
// The only prize is gone, then the EnakCoin are too short: neither play leaves a row.
|
||
|
|
_, err = play()
|
||
|
|
assert.ErrorIs(t, err, ErrGamePlayRefused)
|
||
|
|
require.NoError(t, db.Exec(`UPDATE game_prizes SET stock = 5 WHERE id = ?`, prizeID).Error)
|
||
|
|
_, err = play()
|
||
|
|
assert.ErrorIs(t, err, ErrGamePlayRefused)
|
||
|
|
|
||
|
|
var plays, spends int64
|
||
|
|
require.NoError(t, db.Raw(`SELECT COUNT(*) FROM game_plays WHERE game_id = ? AND coins_used = 2`, gameID).Scan(&plays).Error)
|
||
|
|
require.NoError(t, db.Raw(`SELECT COUNT(*) FROM wallet_transactions WHERE customer_id = ? AND type = 'GAME_SPEND'`, player).Scan(&spends).Error)
|
||
|
|
assert.Equal(t, int64(1), plays)
|
||
|
|
assert.Equal(t, int64(1), spends)
|
||
|
|
}
|