overtime-live-trading-utils 2.1.27 → 2.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +32 -32
- package/.prettierrc +9 -9
- package/CLAUDE.md +77 -0
- package/codecov.yml +20 -20
- package/index.ts +26 -26
- package/jest.config.ts +16 -16
- package/main.js +1 -1
- package/package.json +30 -30
- package/resolution_live_markets.md +351 -0
- package/src/constants/common.ts +7 -7
- package/src/constants/errors.ts +6 -6
- package/src/constants/sports.ts +78 -78
- package/src/enums/sports.ts +109 -109
- package/src/tests/mock/MockLeagueMap.ts +170 -170
- package/src/tests/mock/MockOpticOddsEvents.ts +518 -518
- package/src/tests/mock/MockOpticSoccer.ts +9378 -9378
- package/src/tests/mock/MockSoccerRedis.ts +2308 -2308
- package/src/tests/unit/bookmakers.test.ts +79 -79
- package/src/tests/unit/markets.test.ts +156 -156
- package/src/tests/unit/odds.test.ts +92 -92
- package/src/tests/unit/resolution.test.ts +935 -935
- package/src/tests/unit/sports.test.ts +58 -58
- package/src/tests/unit/spread.test.ts +131 -131
- package/src/types/missing-types.d.ts +2 -2
- package/src/types/odds.ts +61 -61
- package/src/types/resolution.ts +96 -96
- package/src/types/sports.ts +19 -19
- package/src/utils/bookmakers.ts +159 -159
- package/src/utils/constraints.ts +210 -210
- package/src/utils/gameMatching.ts +81 -81
- package/src/utils/markets.ts +119 -119
- package/src/utils/odds.ts +674 -912
- package/src/utils/opticOdds.ts +71 -71
- package/src/utils/resolution.ts +291 -291
- package/src/utils/sports.ts +51 -51
- package/src/utils/spread.ts +97 -97
- package/tsconfig.json +16 -16
- package/webpack.config.js +24 -24
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import { DIFF_BETWEEN_BOOKMAKERS_MESSAGE, ZERO_ODDS_MESSAGE } from '../../constants/errors';
|
|
2
|
-
import { processMarket } from '../../utils/markets';
|
|
3
|
-
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
-
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
-
import { MockOnlyMoneyline, MockOnlyMoneylineWithDifferentSportsbook } from '../mock/MockOpticSoccer';
|
|
6
|
-
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
7
|
-
|
|
8
|
-
describe('Bookmakers', () => {
|
|
9
|
-
it('Should return zero odds for moneyline when one of the bookmakers has no odds', () => {
|
|
10
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
11
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
12
|
-
const market = processMarket(
|
|
13
|
-
freshMockSoccer,
|
|
14
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
15
|
-
['draftkings', 'bovada'],
|
|
16
|
-
[],
|
|
17
|
-
true,
|
|
18
|
-
undefined,
|
|
19
|
-
undefined,
|
|
20
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const hasOdds = market.odds.some(
|
|
24
|
-
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
expect(hasOdds).toBe(false);
|
|
28
|
-
expect(market).toHaveProperty('errorMessage');
|
|
29
|
-
expect(market.errorMessage).toBe(ZERO_ODDS_MESSAGE);
|
|
30
|
-
expect(market.childMarkets.length).toBe(0);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('Should return zero odds for moneyline when there is quote diff between bookmakers', () => {
|
|
34
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
35
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneylineWithDifferentSportsbook));
|
|
36
|
-
const market = processMarket(
|
|
37
|
-
freshMockSoccer,
|
|
38
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
39
|
-
['draftkings', 'bovada'],
|
|
40
|
-
[],
|
|
41
|
-
true,
|
|
42
|
-
undefined,
|
|
43
|
-
5,
|
|
44
|
-
LeagueMocks.leagueInfoOnlyParent
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
const hasOdds = market.odds.some(
|
|
48
|
-
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
expect(hasOdds).toBe(false);
|
|
52
|
-
expect(market).toHaveProperty('errorMessage');
|
|
53
|
-
expect(market.errorMessage).toBe(DIFF_BETWEEN_BOOKMAKERS_MESSAGE);
|
|
54
|
-
expect(market.childMarkets.length).toBe(0);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('Should return zero odds for moneyline as no matching bookmaker was provided', () => {
|
|
58
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
59
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
60
|
-
const market = processMarket(
|
|
61
|
-
freshMockSoccer,
|
|
62
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
63
|
-
['bovada', 'draftkings'],
|
|
64
|
-
[],
|
|
65
|
-
true,
|
|
66
|
-
undefined,
|
|
67
|
-
undefined,
|
|
68
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const hasOdds = market.odds.some(
|
|
72
|
-
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
expect(hasOdds).toBe(false);
|
|
76
|
-
expect(market).toHaveProperty('errorMessage');
|
|
77
|
-
expect(market.errorMessage).toBe(ZERO_ODDS_MESSAGE); // should be no matching bookmakers mesage
|
|
78
|
-
});
|
|
79
|
-
});
|
|
1
|
+
import { DIFF_BETWEEN_BOOKMAKERS_MESSAGE, ZERO_ODDS_MESSAGE } from '../../constants/errors';
|
|
2
|
+
import { processMarket } from '../../utils/markets';
|
|
3
|
+
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
+
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
+
import { MockOnlyMoneyline, MockOnlyMoneylineWithDifferentSportsbook } from '../mock/MockOpticSoccer';
|
|
6
|
+
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
7
|
+
|
|
8
|
+
describe('Bookmakers', () => {
|
|
9
|
+
it('Should return zero odds for moneyline when one of the bookmakers has no odds', () => {
|
|
10
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
11
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
12
|
+
const market = processMarket(
|
|
13
|
+
freshMockSoccer,
|
|
14
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
15
|
+
['draftkings', 'bovada'],
|
|
16
|
+
[],
|
|
17
|
+
true,
|
|
18
|
+
undefined,
|
|
19
|
+
undefined,
|
|
20
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const hasOdds = market.odds.some(
|
|
24
|
+
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(hasOdds).toBe(false);
|
|
28
|
+
expect(market).toHaveProperty('errorMessage');
|
|
29
|
+
expect(market.errorMessage).toBe(ZERO_ODDS_MESSAGE);
|
|
30
|
+
expect(market.childMarkets.length).toBe(0);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('Should return zero odds for moneyline when there is quote diff between bookmakers', () => {
|
|
34
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
35
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneylineWithDifferentSportsbook));
|
|
36
|
+
const market = processMarket(
|
|
37
|
+
freshMockSoccer,
|
|
38
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
39
|
+
['draftkings', 'bovada'],
|
|
40
|
+
[],
|
|
41
|
+
true,
|
|
42
|
+
undefined,
|
|
43
|
+
5,
|
|
44
|
+
LeagueMocks.leagueInfoOnlyParent
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const hasOdds = market.odds.some(
|
|
48
|
+
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(hasOdds).toBe(false);
|
|
52
|
+
expect(market).toHaveProperty('errorMessage');
|
|
53
|
+
expect(market.errorMessage).toBe(DIFF_BETWEEN_BOOKMAKERS_MESSAGE);
|
|
54
|
+
expect(market.childMarkets.length).toBe(0);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('Should return zero odds for moneyline as no matching bookmaker was provided', () => {
|
|
58
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
59
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
60
|
+
const market = processMarket(
|
|
61
|
+
freshMockSoccer,
|
|
62
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
63
|
+
['bovada', 'draftkings'],
|
|
64
|
+
[],
|
|
65
|
+
true,
|
|
66
|
+
undefined,
|
|
67
|
+
undefined,
|
|
68
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const hasOdds = market.odds.some(
|
|
72
|
+
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
expect(hasOdds).toBe(false);
|
|
76
|
+
expect(market).toHaveProperty('errorMessage');
|
|
77
|
+
expect(market.errorMessage).toBe(ZERO_ODDS_MESSAGE); // should be no matching bookmakers mesage
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -1,156 +1,156 @@
|
|
|
1
|
-
import { NO_MARKETS_FOR_LEAGUE_ID } from '../../constants/errors';
|
|
2
|
-
import { processMarket } from '../../utils/markets';
|
|
3
|
-
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
-
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
-
import { MockOnlyMoneyline, MockOpticSoccer } from '../mock/MockOpticSoccer';
|
|
6
|
-
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
7
|
-
|
|
8
|
-
describe('Markets', () => {
|
|
9
|
-
describe('LeagueMap configuration', () => {
|
|
10
|
-
it('Should return an empty array for child markets when they are not added to list', () => {
|
|
11
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
12
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
13
|
-
|
|
14
|
-
const market = processMarket(
|
|
15
|
-
freshMockSoccer,
|
|
16
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
17
|
-
['draftkings'],
|
|
18
|
-
[],
|
|
19
|
-
true,
|
|
20
|
-
undefined,
|
|
21
|
-
undefined,
|
|
22
|
-
LeagueMocks.leagueInfoOnlyParent
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
expect(market.childMarkets).toHaveLength(0);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('Should return an empty array for child markets when they are disabled', () => {
|
|
29
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
30
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
31
|
-
const market = processMarket(
|
|
32
|
-
freshMockSoccer,
|
|
33
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
34
|
-
['draftkings'],
|
|
35
|
-
[],
|
|
36
|
-
true,
|
|
37
|
-
undefined,
|
|
38
|
-
undefined,
|
|
39
|
-
LeagueMocks.leagueInfoMockDisabledChilds
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
expect(market.childMarkets).toHaveLength(0);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('Should return only spread child markets without total child markets', () => {
|
|
46
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
47
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
48
|
-
const market = processMarket(
|
|
49
|
-
freshMockSoccer,
|
|
50
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
51
|
-
['draftkings'],
|
|
52
|
-
[],
|
|
53
|
-
true,
|
|
54
|
-
undefined,
|
|
55
|
-
undefined,
|
|
56
|
-
LeagueMocks.leagueInfoEnabledSpreadDisabledTotals
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
|
|
60
|
-
const containsTotal = market.childMarkets.some((child: any) => child.type === 'total');
|
|
61
|
-
|
|
62
|
-
expect(containsSpread).toBe(true);
|
|
63
|
-
expect(containsTotal).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('Should return both totals and spread child markets', () => {
|
|
67
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
68
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
69
|
-
const market = processMarket(
|
|
70
|
-
freshMockSoccer,
|
|
71
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
72
|
-
['draftkings'],
|
|
73
|
-
[],
|
|
74
|
-
true,
|
|
75
|
-
undefined,
|
|
76
|
-
undefined,
|
|
77
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
|
|
81
|
-
const containsTotal = market.childMarkets.some((child: any) => child.type === 'total');
|
|
82
|
-
|
|
83
|
-
expect(containsSpread).toBe(true);
|
|
84
|
-
expect(containsTotal).toBe(true);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('Should return all child markets', () => {
|
|
88
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
89
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
90
|
-
const market = processMarket(
|
|
91
|
-
freshMockSoccer,
|
|
92
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
93
|
-
['draftkings'],
|
|
94
|
-
[],
|
|
95
|
-
true,
|
|
96
|
-
undefined,
|
|
97
|
-
undefined,
|
|
98
|
-
LeagueMocks.leagueInfoEnabledAll
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
|
|
102
|
-
const containsTotal = market.childMarkets.some((child: any) => child.type === 'total');
|
|
103
|
-
const containsChildMoneyline = market.childMarkets.some(
|
|
104
|
-
(child: any) => child.type === 'secondPeriodWinner'
|
|
105
|
-
);
|
|
106
|
-
const containsChildCorrectScore = market.childMarkets.some((child: any) => child.type === 'correctScore');
|
|
107
|
-
const containsChildDoubleChance = market.childMarkets.some((child: any) => child.type === 'doubleChance');
|
|
108
|
-
const containsChildGG = market.childMarkets.some((child: any) => child.type === 'bothTeamsToScore');
|
|
109
|
-
const containsChildGG1stHalf = market.childMarkets.some(
|
|
110
|
-
(child: any) => child.type === 'firstPeriodBothTeamsToScore'
|
|
111
|
-
);
|
|
112
|
-
const containsChildGG2ndHalf = market.childMarkets.some(
|
|
113
|
-
(child: any) => child.type === 'secondPeriodBothTeamsToScore'
|
|
114
|
-
);
|
|
115
|
-
const containsChildDrawNoBet = market.childMarkets.some((child: any) => child.type === 'drawNoBet');
|
|
116
|
-
const containsWillThereBeOvertime = market.childMarkets.some(
|
|
117
|
-
(child: any) => child.type === 'willThereBeOvertime'
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
expect(containsChildGG).toBe(true);
|
|
121
|
-
expect(containsChildGG1stHalf).toBe(true);
|
|
122
|
-
expect(containsChildGG2ndHalf).toBe(true);
|
|
123
|
-
expect(containsSpread).toBe(true);
|
|
124
|
-
expect(containsTotal).toBe(true);
|
|
125
|
-
expect(containsChildMoneyline).toBe(true);
|
|
126
|
-
expect(containsChildCorrectScore).toBe(true);
|
|
127
|
-
expect(containsChildDoubleChance).toBe(true);
|
|
128
|
-
expect(containsChildGG).toBe(true);
|
|
129
|
-
expect(containsChildDrawNoBet).toBe(true);
|
|
130
|
-
expect(containsWillThereBeOvertime).toBe(true);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('Should return warning message that there are is no configuration available in league map csv', () => {
|
|
134
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
135
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
136
|
-
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
137
|
-
|
|
138
|
-
processMarket(
|
|
139
|
-
freshMockSoccer,
|
|
140
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
141
|
-
['draftkings'],
|
|
142
|
-
[],
|
|
143
|
-
true,
|
|
144
|
-
undefined,
|
|
145
|
-
undefined,
|
|
146
|
-
LeagueMocks.leagueInfoOnlyParentDiffSportId
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
expect(warnSpy).toHaveBeenCalled();
|
|
150
|
-
expect(warnSpy).toHaveBeenCalledWith(`${NO_MARKETS_FOR_LEAGUE_ID}: ${Number(mockSoccer.leagueId)}`);
|
|
151
|
-
|
|
152
|
-
// Restore the original implementation
|
|
153
|
-
warnSpy.mockRestore();
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
});
|
|
1
|
+
import { NO_MARKETS_FOR_LEAGUE_ID } from '../../constants/errors';
|
|
2
|
+
import { processMarket } from '../../utils/markets';
|
|
3
|
+
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
+
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
+
import { MockOnlyMoneyline, MockOpticSoccer } from '../mock/MockOpticSoccer';
|
|
6
|
+
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
7
|
+
|
|
8
|
+
describe('Markets', () => {
|
|
9
|
+
describe('LeagueMap configuration', () => {
|
|
10
|
+
it('Should return an empty array for child markets when they are not added to list', () => {
|
|
11
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
12
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
13
|
+
|
|
14
|
+
const market = processMarket(
|
|
15
|
+
freshMockSoccer,
|
|
16
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
17
|
+
['draftkings'],
|
|
18
|
+
[],
|
|
19
|
+
true,
|
|
20
|
+
undefined,
|
|
21
|
+
undefined,
|
|
22
|
+
LeagueMocks.leagueInfoOnlyParent
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
expect(market.childMarkets).toHaveLength(0);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('Should return an empty array for child markets when they are disabled', () => {
|
|
29
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
30
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
31
|
+
const market = processMarket(
|
|
32
|
+
freshMockSoccer,
|
|
33
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
34
|
+
['draftkings'],
|
|
35
|
+
[],
|
|
36
|
+
true,
|
|
37
|
+
undefined,
|
|
38
|
+
undefined,
|
|
39
|
+
LeagueMocks.leagueInfoMockDisabledChilds
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
expect(market.childMarkets).toHaveLength(0);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('Should return only spread child markets without total child markets', () => {
|
|
46
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
47
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
48
|
+
const market = processMarket(
|
|
49
|
+
freshMockSoccer,
|
|
50
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
51
|
+
['draftkings'],
|
|
52
|
+
[],
|
|
53
|
+
true,
|
|
54
|
+
undefined,
|
|
55
|
+
undefined,
|
|
56
|
+
LeagueMocks.leagueInfoEnabledSpreadDisabledTotals
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
|
|
60
|
+
const containsTotal = market.childMarkets.some((child: any) => child.type === 'total');
|
|
61
|
+
|
|
62
|
+
expect(containsSpread).toBe(true);
|
|
63
|
+
expect(containsTotal).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('Should return both totals and spread child markets', () => {
|
|
67
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
68
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
69
|
+
const market = processMarket(
|
|
70
|
+
freshMockSoccer,
|
|
71
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
72
|
+
['draftkings'],
|
|
73
|
+
[],
|
|
74
|
+
true,
|
|
75
|
+
undefined,
|
|
76
|
+
undefined,
|
|
77
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
|
|
81
|
+
const containsTotal = market.childMarkets.some((child: any) => child.type === 'total');
|
|
82
|
+
|
|
83
|
+
expect(containsSpread).toBe(true);
|
|
84
|
+
expect(containsTotal).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('Should return all child markets', () => {
|
|
88
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
89
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOpticSoccer));
|
|
90
|
+
const market = processMarket(
|
|
91
|
+
freshMockSoccer,
|
|
92
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
93
|
+
['draftkings'],
|
|
94
|
+
[],
|
|
95
|
+
true,
|
|
96
|
+
undefined,
|
|
97
|
+
undefined,
|
|
98
|
+
LeagueMocks.leagueInfoEnabledAll
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const containsSpread = market.childMarkets.some((child: any) => child.type === 'spread');
|
|
102
|
+
const containsTotal = market.childMarkets.some((child: any) => child.type === 'total');
|
|
103
|
+
const containsChildMoneyline = market.childMarkets.some(
|
|
104
|
+
(child: any) => child.type === 'secondPeriodWinner'
|
|
105
|
+
);
|
|
106
|
+
const containsChildCorrectScore = market.childMarkets.some((child: any) => child.type === 'correctScore');
|
|
107
|
+
const containsChildDoubleChance = market.childMarkets.some((child: any) => child.type === 'doubleChance');
|
|
108
|
+
const containsChildGG = market.childMarkets.some((child: any) => child.type === 'bothTeamsToScore');
|
|
109
|
+
const containsChildGG1stHalf = market.childMarkets.some(
|
|
110
|
+
(child: any) => child.type === 'firstPeriodBothTeamsToScore'
|
|
111
|
+
);
|
|
112
|
+
const containsChildGG2ndHalf = market.childMarkets.some(
|
|
113
|
+
(child: any) => child.type === 'secondPeriodBothTeamsToScore'
|
|
114
|
+
);
|
|
115
|
+
const containsChildDrawNoBet = market.childMarkets.some((child: any) => child.type === 'drawNoBet');
|
|
116
|
+
const containsWillThereBeOvertime = market.childMarkets.some(
|
|
117
|
+
(child: any) => child.type === 'willThereBeOvertime'
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
expect(containsChildGG).toBe(true);
|
|
121
|
+
expect(containsChildGG1stHalf).toBe(true);
|
|
122
|
+
expect(containsChildGG2ndHalf).toBe(true);
|
|
123
|
+
expect(containsSpread).toBe(true);
|
|
124
|
+
expect(containsTotal).toBe(true);
|
|
125
|
+
expect(containsChildMoneyline).toBe(true);
|
|
126
|
+
expect(containsChildCorrectScore).toBe(true);
|
|
127
|
+
expect(containsChildDoubleChance).toBe(true);
|
|
128
|
+
expect(containsChildGG).toBe(true);
|
|
129
|
+
expect(containsChildDrawNoBet).toBe(true);
|
|
130
|
+
expect(containsWillThereBeOvertime).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('Should return warning message that there are is no configuration available in league map csv', () => {
|
|
134
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
135
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
136
|
+
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
137
|
+
|
|
138
|
+
processMarket(
|
|
139
|
+
freshMockSoccer,
|
|
140
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
141
|
+
['draftkings'],
|
|
142
|
+
[],
|
|
143
|
+
true,
|
|
144
|
+
undefined,
|
|
145
|
+
undefined,
|
|
146
|
+
LeagueMocks.leagueInfoOnlyParentDiffSportId
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(warnSpy).toHaveBeenCalled();
|
|
150
|
+
expect(warnSpy).toHaveBeenCalledWith(`${NO_MARKETS_FOR_LEAGUE_ID}: ${Number(mockSoccer.leagueId)}`);
|
|
151
|
+
|
|
152
|
+
// Restore the original implementation
|
|
153
|
+
warnSpy.mockRestore();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
import { ZERO_ODDS_MESSAGE_SINGLE_BOOKMAKER } from '../../constants/errors';
|
|
2
|
-
import { processMarket } from '../../utils/markets';
|
|
3
|
-
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
-
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
-
import {
|
|
6
|
-
MockOddsChildMarketsGoodOdds,
|
|
7
|
-
MockOddsChildMarketsOddsCut,
|
|
8
|
-
MockOnlyMoneyline,
|
|
9
|
-
MockZeroOdds,
|
|
10
|
-
} from '../mock/MockOpticSoccer';
|
|
11
|
-
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
12
|
-
|
|
13
|
-
describe('Odds', () => {
|
|
14
|
-
it('Should return odds for moneyline', () => {
|
|
15
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
16
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
17
|
-
const market = processMarket(
|
|
18
|
-
freshMockSoccer,
|
|
19
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
20
|
-
['draftkings'],
|
|
21
|
-
[],
|
|
22
|
-
true,
|
|
23
|
-
undefined,
|
|
24
|
-
undefined,
|
|
25
|
-
LeagueMocks.leagueInfoOnlyParent
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
const hasOdds = market.odds.some(
|
|
29
|
-
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
expect(hasOdds).toBe(true);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('Should return zero odds for moneyline', () => {
|
|
36
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
37
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockZeroOdds));
|
|
38
|
-
const market = processMarket(
|
|
39
|
-
freshMockSoccer,
|
|
40
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
41
|
-
['draftkings'],
|
|
42
|
-
[],
|
|
43
|
-
true,
|
|
44
|
-
undefined,
|
|
45
|
-
undefined,
|
|
46
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const hasOdds = market.odds.some(
|
|
50
|
-
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
expect(hasOdds).toBe(false);
|
|
54
|
-
expect(market).toHaveProperty('errorMessage');
|
|
55
|
-
expect(market.errorMessage).toBe(ZERO_ODDS_MESSAGE_SINGLE_BOOKMAKER);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('Should contain child markets for good odds', () => {
|
|
59
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
60
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOddsChildMarketsGoodOdds));
|
|
61
|
-
const market = processMarket(
|
|
62
|
-
freshMockSoccer,
|
|
63
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
64
|
-
['draftkings'],
|
|
65
|
-
[],
|
|
66
|
-
true,
|
|
67
|
-
undefined,
|
|
68
|
-
undefined,
|
|
69
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const hasChildMarkets = market.childMarkets.length > 0;
|
|
73
|
-
expect(hasChildMarkets).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('Should return empty array for child child markets after odds cut', () => {
|
|
77
|
-
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
78
|
-
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOddsChildMarketsOddsCut));
|
|
79
|
-
const market = processMarket(
|
|
80
|
-
freshMockSoccer,
|
|
81
|
-
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
82
|
-
['draftkings'],
|
|
83
|
-
[],
|
|
84
|
-
true,
|
|
85
|
-
undefined,
|
|
86
|
-
undefined,
|
|
87
|
-
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
expect(market.childMarkets).toHaveLength(0);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
1
|
+
import { ZERO_ODDS_MESSAGE_SINGLE_BOOKMAKER } from '../../constants/errors';
|
|
2
|
+
import { processMarket } from '../../utils/markets';
|
|
3
|
+
import { mapOpticOddsApiFixtureOdds } from '../../utils/opticOdds';
|
|
4
|
+
import { LeagueMocks } from '../mock/MockLeagueMap';
|
|
5
|
+
import {
|
|
6
|
+
MockOddsChildMarketsGoodOdds,
|
|
7
|
+
MockOddsChildMarketsOddsCut,
|
|
8
|
+
MockOnlyMoneyline,
|
|
9
|
+
MockZeroOdds,
|
|
10
|
+
} from '../mock/MockOpticSoccer';
|
|
11
|
+
import { mockSoccer } from '../mock/MockSoccerRedis';
|
|
12
|
+
|
|
13
|
+
describe('Odds', () => {
|
|
14
|
+
it('Should return odds for moneyline', () => {
|
|
15
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
16
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOnlyMoneyline));
|
|
17
|
+
const market = processMarket(
|
|
18
|
+
freshMockSoccer,
|
|
19
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
20
|
+
['draftkings'],
|
|
21
|
+
[],
|
|
22
|
+
true,
|
|
23
|
+
undefined,
|
|
24
|
+
undefined,
|
|
25
|
+
LeagueMocks.leagueInfoOnlyParent
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const hasOdds = market.odds.some(
|
|
29
|
+
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(hasOdds).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('Should return zero odds for moneyline', () => {
|
|
36
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
37
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockZeroOdds));
|
|
38
|
+
const market = processMarket(
|
|
39
|
+
freshMockSoccer,
|
|
40
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
41
|
+
['draftkings'],
|
|
42
|
+
[],
|
|
43
|
+
true,
|
|
44
|
+
undefined,
|
|
45
|
+
undefined,
|
|
46
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const hasOdds = market.odds.some(
|
|
50
|
+
(odd: any) => odd.american !== 0 || odd.decimal !== 0 || odd.normalizedImplied !== 0
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(hasOdds).toBe(false);
|
|
54
|
+
expect(market).toHaveProperty('errorMessage');
|
|
55
|
+
expect(market.errorMessage).toBe(ZERO_ODDS_MESSAGE_SINGLE_BOOKMAKER);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('Should contain child markets for good odds', () => {
|
|
59
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
60
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOddsChildMarketsGoodOdds));
|
|
61
|
+
const market = processMarket(
|
|
62
|
+
freshMockSoccer,
|
|
63
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
64
|
+
['draftkings'],
|
|
65
|
+
[],
|
|
66
|
+
true,
|
|
67
|
+
undefined,
|
|
68
|
+
undefined,
|
|
69
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const hasChildMarkets = market.childMarkets.length > 0;
|
|
73
|
+
expect(hasChildMarkets).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('Should return empty array for child child markets after odds cut', () => {
|
|
77
|
+
const freshMockSoccer = JSON.parse(JSON.stringify(mockSoccer));
|
|
78
|
+
const freshMockOpticSoccer = JSON.parse(JSON.stringify(MockOddsChildMarketsOddsCut));
|
|
79
|
+
const market = processMarket(
|
|
80
|
+
freshMockSoccer,
|
|
81
|
+
mapOpticOddsApiFixtureOdds([freshMockOpticSoccer])[0],
|
|
82
|
+
['draftkings'],
|
|
83
|
+
[],
|
|
84
|
+
true,
|
|
85
|
+
undefined,
|
|
86
|
+
undefined,
|
|
87
|
+
LeagueMocks.leagueInfoEnabledSpeadAndTotals
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(market.childMarkets).toHaveLength(0);
|
|
91
|
+
});
|
|
92
|
+
});
|