- Added evaluation functions for NFL money line, spread, and total points. - Implemented evaluation functions for Rugby money line, spread, and total points. - Created evaluation functions for Baseball money line, spread, total runs, first inning, and first 5 innings. - Developed unit tests for all sports markets to ensure correct evaluation outcomes. - Introduced ResultCheckerService to handle game result checking for NFL, Rugby, and Baseball. - Updated routes to include new functionality for virtual game handling.
304 lines
16 KiB
Go
304 lines
16 KiB
Go
package result
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// TestNFLMarkets covers all American Football (NFL) market types defined in the domain.
|
|
// For each market (Money Line, Spread, Total Points), it tests home/away win, draw, void, and invalid input scenarios.
|
|
func TestNFLMarkets(t *testing.T) {
|
|
t.Log("Testing NFL (American Football) Markets")
|
|
markets := []struct {
|
|
marketID int64
|
|
name string
|
|
}{
|
|
{int64(domain.AMERICAN_FOOTBALL_MONEY_LINE), "MONEY_LINE"},
|
|
{int64(domain.AMERICAN_FOOTBALL_SPREAD), "SPREAD"},
|
|
{int64(domain.AMERICAN_FOOTBALL_TOTAL_POINTS), "TOTAL_POINTS"},
|
|
}
|
|
|
|
for _, m := range markets {
|
|
t.Run(m.name, func(t *testing.T) {
|
|
// Each subtest below covers a key scenario for the given NFL market.
|
|
switch m.marketID {
|
|
case int64(domain.AMERICAN_FOOTBALL_MONEY_LINE):
|
|
// Home win, away win, draw, and invalid OddHeader for Money Line
|
|
t.Run("Home Win", func(t *testing.T) {
|
|
status, err := evaluateNFLMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1"}, struct{ Home, Away int }{Home: 21, Away: 14})
|
|
t.Logf("Market: %s, Scenario: Home Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Away Win", func(t *testing.T) {
|
|
status, err := evaluateNFLMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "2"}, struct{ Home, Away int }{Home: 14, Away: 21})
|
|
t.Logf("Market: %s, Scenario: Away Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Draw", func(t *testing.T) {
|
|
status, err := evaluateNFLMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1"}, struct{ Home, Away int }{Home: 17, Away: 17})
|
|
t.Logf("Market: %s, Scenario: Draw", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_LOSS, status)
|
|
})
|
|
t.Run("Invalid OddHeader", func(t *testing.T) {
|
|
status, err := evaluateNFLMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "X"}, struct{ Home, Away int }{Home: 10, Away: 7})
|
|
t.Logf("Market: %s, Scenario: Invalid OddHeader", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
case int64(domain.AMERICAN_FOOTBALL_SPREAD):
|
|
t.Run("Home Win with Handicap", func(t *testing.T) {
|
|
status, err := evaluateNFLSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "-3.5"}, struct{ Home, Away int }{Home: 24, Away: 20})
|
|
t.Logf("Market: %s, Scenario: Home Win with Handicap", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Away Win with Handicap", func(t *testing.T) {
|
|
status, err := evaluateNFLSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "2", OddHandicap: "+3.5"}, struct{ Home, Away int }{Home: 20, Away: 24})
|
|
t.Logf("Market: %s, Scenario: Away Win with Handicap", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Push (Void)", func(t *testing.T) {
|
|
status, err := evaluateNFLSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "0"}, struct{ Home, Away int }{Home: 21, Away: 21})
|
|
t.Logf("Market: %s, Scenario: Push (Void)", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_VOID, status)
|
|
})
|
|
t.Run("Non-numeric Handicap", func(t *testing.T) {
|
|
status, err := evaluateNFLSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "notanumber"}, struct{ Home, Away int }{Home: 21, Away: 14})
|
|
t.Logf("Market: %s, Scenario: Non-numeric Handicap", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
case int64(domain.AMERICAN_FOOTBALL_TOTAL_POINTS):
|
|
t.Run("Over Win", func(t *testing.T) {
|
|
status, err := evaluateNFLTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "44.5"}, struct{ Home, Away int }{Home: 30, Away: 20})
|
|
t.Logf("Market: %s, Scenario: Over Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Under Win", func(t *testing.T) {
|
|
status, err := evaluateNFLTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Under", OddName: "44.5"}, struct{ Home, Away int }{Home: 20, Away: 17})
|
|
t.Logf("Market: %s, Scenario: Under Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Push (Void)", func(t *testing.T) {
|
|
status, err := evaluateNFLTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "37"}, struct{ Home, Away int }{Home: 20, Away: 17})
|
|
t.Logf("Market: %s, Scenario: Push (Void)", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_VOID, status)
|
|
})
|
|
t.Run("Non-numeric OddName", func(t *testing.T) {
|
|
status, err := evaluateNFLTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "notanumber"}, struct{ Home, Away int }{Home: 20, Away: 17})
|
|
t.Logf("Market: %s, Scenario: Non-numeric OddName", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestRugbyMarkets covers all Rugby (Union & League) market types defined in the domain.
|
|
// For each market (Money Line, Spread, Handicap, Total Points), it tests home/away win, draw, void, and invalid input scenarios.
|
|
func TestRugbyMarkets(t *testing.T) {
|
|
t.Log("Testing Rugby Markets (Union & League)")
|
|
markets := []struct {
|
|
marketID int64
|
|
name string
|
|
}{
|
|
{int64(domain.RUGBY_MONEY_LINE), "MONEY_LINE"},
|
|
{int64(domain.RUGBY_SPREAD), "SPREAD"},
|
|
{int64(domain.RUGBY_TOTAL_POINTS), "TOTAL_POINTS"},
|
|
{int64(domain.RUGBY_HANDICAP), "HANDICAP"},
|
|
}
|
|
|
|
for _, m := range markets {
|
|
t.Run(m.name, func(t *testing.T) {
|
|
// Each subtest below covers a key scenario for the given Rugby market.
|
|
switch m.marketID {
|
|
case int64(domain.RUGBY_MONEY_LINE):
|
|
// Home win, away win, draw, and invalid OddHeader for Money Line
|
|
t.Run("Home Win", func(t *testing.T) {
|
|
status, err := evaluateRugbyMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1"}, struct{ Home, Away int }{Home: 30, Away: 20})
|
|
t.Logf("Market: %s, Scenario: Home Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Away Win", func(t *testing.T) {
|
|
status, err := evaluateRugbyMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "2"}, struct{ Home, Away int }{Home: 20, Away: 30})
|
|
t.Logf("Market: %s, Scenario: Away Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Draw", func(t *testing.T) {
|
|
status, err := evaluateRugbyMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1"}, struct{ Home, Away int }{Home: 25, Away: 25})
|
|
t.Logf("Market: %s, Scenario: Draw", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_LOSS, status)
|
|
})
|
|
t.Run("Invalid OddHeader", func(t *testing.T) {
|
|
status, err := evaluateRugbyMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "X"}, struct{ Home, Away int }{Home: 10, Away: 7})
|
|
t.Logf("Market: %s, Scenario: Invalid OddHeader", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
case int64(domain.RUGBY_SPREAD), int64(domain.RUGBY_HANDICAP):
|
|
t.Run("Home Win with Handicap", func(t *testing.T) {
|
|
status, err := evaluateRugbySpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "-6.5"}, struct{ Home, Away int }{Home: 28, Away: 20})
|
|
t.Logf("Market: %s, Scenario: Home Win with Handicap", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Away Win with Handicap", func(t *testing.T) {
|
|
status, err := evaluateRugbySpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "2", OddHandicap: "+6.5"}, struct{ Home, Away int }{Home: 20, Away: 28})
|
|
t.Logf("Market: %s, Scenario: Away Win with Handicap", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Push (Void)", func(t *testing.T) {
|
|
status, err := evaluateRugbySpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "0"}, struct{ Home, Away int }{Home: 21, Away: 21})
|
|
t.Logf("Market: %s, Scenario: Push (Void)", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_VOID, status)
|
|
})
|
|
t.Run("Non-numeric Handicap", func(t *testing.T) {
|
|
status, err := evaluateRugbySpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "notanumber"}, struct{ Home, Away int }{Home: 21, Away: 14})
|
|
t.Logf("Market: %s, Scenario: Non-numeric Handicap", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
case int64(domain.RUGBY_TOTAL_POINTS):
|
|
t.Run("Over Win", func(t *testing.T) {
|
|
status, err := evaluateRugbyTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "40.5"}, struct{ Home, Away int }{Home: 25, Away: 20})
|
|
t.Logf("Market: %s, Scenario: Over Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Under Win", func(t *testing.T) {
|
|
status, err := evaluateRugbyTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Under", OddName: "40.5"}, struct{ Home, Away int }{Home: 15, Away: 20})
|
|
t.Logf("Market: %s, Scenario: Under Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Push (Void)", func(t *testing.T) {
|
|
status, err := evaluateRugbyTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "35"}, struct{ Home, Away int }{Home: 20, Away: 15})
|
|
t.Logf("Market: %s, Scenario: Push (Void)", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_VOID, status)
|
|
})
|
|
t.Run("Non-numeric OddName", func(t *testing.T) {
|
|
status, err := evaluateRugbyTotalPoints(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "notanumber"}, struct{ Home, Away int }{Home: 20, Away: 15})
|
|
t.Logf("Market: %s, Scenario: Non-numeric OddName", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestBaseballMarkets covers all Baseball market types defined in the domain.
|
|
// For each market (Money Line, Spread, Total Runs), it tests home/away win, draw, void, and invalid input scenarios.
|
|
func TestBaseballMarkets(t *testing.T) {
|
|
t.Log("Testing Baseball Markets")
|
|
markets := []struct {
|
|
marketID int64
|
|
name string
|
|
}{
|
|
{int64(domain.BASEBALL_MONEY_LINE), "MONEY_LINE"},
|
|
{int64(domain.BASEBALL_SPREAD), "SPREAD"},
|
|
{int64(domain.BASEBALL_TOTAL_RUNS), "TOTAL_RUNS"},
|
|
}
|
|
|
|
for _, m := range markets {
|
|
t.Run(m.name, func(t *testing.T) {
|
|
// Each subtest below covers a key scenario for the given Baseball market.
|
|
switch m.marketID {
|
|
case int64(domain.BASEBALL_MONEY_LINE):
|
|
// Home win, away win, draw, and invalid OddHeader for Money Line
|
|
t.Run("Home Win", func(t *testing.T) {
|
|
status, err := evaluateBaseballMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1"}, struct{ Home, Away int }{Home: 6, Away: 3})
|
|
t.Logf("Market: %s, Scenario: Home Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Away Win", func(t *testing.T) {
|
|
status, err := evaluateBaseballMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "2"}, struct{ Home, Away int }{Home: 2, Away: 5})
|
|
t.Logf("Market: %s, Scenario: Away Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Draw", func(t *testing.T) {
|
|
status, err := evaluateBaseballMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1"}, struct{ Home, Away int }{Home: 4, Away: 4})
|
|
t.Logf("Market: %s, Scenario: Draw", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_LOSS, status)
|
|
})
|
|
t.Run("Invalid OddHeader", func(t *testing.T) {
|
|
status, err := evaluateBaseballMoneyLine(domain.BetOutcome{MarketID: m.marketID, OddHeader: "X"}, struct{ Home, Away int }{Home: 10, Away: 7})
|
|
t.Logf("Market: %s, Scenario: Invalid OddHeader", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
case int64(domain.BASEBALL_SPREAD):
|
|
t.Run("Home Win with Handicap", func(t *testing.T) {
|
|
status, err := evaluateBaseballSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "-1.5"}, struct{ Home, Away int }{Home: 5, Away: 3})
|
|
t.Logf("Market: %s, Scenario: Home Win with Handicap", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Away Win with Handicap", func(t *testing.T) {
|
|
status, err := evaluateBaseballSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "2", OddHandicap: "+1.5"}, struct{ Home, Away int }{Home: 3, Away: 5})
|
|
t.Logf("Market: %s, Scenario: Away Win with Handicap", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Push (Void)", func(t *testing.T) {
|
|
status, err := evaluateBaseballSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "0"}, struct{ Home, Away int }{Home: 4, Away: 4})
|
|
t.Logf("Market: %s, Scenario: Push (Void)", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_VOID, status)
|
|
})
|
|
t.Run("Non-numeric Handicap", func(t *testing.T) {
|
|
status, err := evaluateBaseballSpread(domain.BetOutcome{MarketID: m.marketID, OddHeader: "1", OddHandicap: "notanumber"}, struct{ Home, Away int }{Home: 5, Away: 3})
|
|
t.Logf("Market: %s, Scenario: Non-numeric Handicap", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
case int64(domain.BASEBALL_TOTAL_RUNS):
|
|
t.Run("Over Win", func(t *testing.T) {
|
|
status, err := evaluateBaseballTotalRuns(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "7.5"}, struct{ Home, Away int }{Home: 5, Away: 4})
|
|
t.Logf("Market: %s, Scenario: Over Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Under Win", func(t *testing.T) {
|
|
status, err := evaluateBaseballTotalRuns(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Under", OddName: "7.5"}, struct{ Home, Away int }{Home: 2, Away: 3})
|
|
t.Logf("Market: %s, Scenario: Under Win", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_WIN, status)
|
|
})
|
|
t.Run("Push (Void)", func(t *testing.T) {
|
|
status, err := evaluateBaseballTotalRuns(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "7"}, struct{ Home, Away int }{Home: 4, Away: 3})
|
|
t.Logf("Market: %s, Scenario: Push (Void)", m.name)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_VOID, status)
|
|
})
|
|
t.Run("Non-numeric OddName", func(t *testing.T) {
|
|
status, err := evaluateBaseballTotalRuns(domain.BetOutcome{MarketID: m.marketID, OddHeader: "Over", OddName: "notanumber"}, struct{ Home, Away int }{Home: 4, Away: 3})
|
|
t.Logf("Market: %s, Scenario: Non-numeric OddName", m.name)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, domain.OUTCOME_STATUS_PENDING, status)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|