初始化
This commit is contained in:
@@ -0,0 +1,463 @@
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
|
||||
const registerPlayerPromotionRedeemRoute = require('../src/routes/ewl/bal/playerPromotionRedeem')
|
||||
|
||||
const {
|
||||
ISSUE_TARGET_TO_WALLET_HEADER,
|
||||
bridgePromotionRedeemToEwallet,
|
||||
createMockPromotionRedeemResult,
|
||||
isBackdatePromotionRedeemRequest,
|
||||
registerableRoutes,
|
||||
mergeIssueTargetToWalletOverrides,
|
||||
mergeRuntimeIssueTargetToWalletOverrides,
|
||||
resolveIssueTargetToWallet,
|
||||
} = registerPlayerPromotionRedeemRoute.__internal
|
||||
|
||||
test('registers both normal and backdate promotion redeem routes', () => {
|
||||
assert.deepEqual(registerableRoutes, [
|
||||
'/ewl/promotion/v1/playerpromotion/redeem',
|
||||
'/ewl/promotion/v1/playerpromotion/redeemBackDate',
|
||||
'/ewl/bal/v1/playerpromotion/redeem',
|
||||
'/ewl/bal/v1/playerpromotion/redeemBackDate',
|
||||
])
|
||||
})
|
||||
|
||||
test('detects backdate redeem requests from route and payload', () => {
|
||||
assert.equal(
|
||||
isBackdatePromotionRedeemRequest('/ewl/promotion/v1/playerpromotion/redeemBackDate', {
|
||||
data: {},
|
||||
}),
|
||||
true,
|
||||
)
|
||||
assert.equal(
|
||||
isBackdatePromotionRedeemRequest('/ewl/promotion/v1/playerpromotion/redeem', {
|
||||
data: { backdate: '2026-03-23' },
|
||||
}),
|
||||
true,
|
||||
)
|
||||
assert.equal(
|
||||
isBackdatePromotionRedeemRequest('/ewl/promotion/v1/playerpromotion/redeem', {
|
||||
data: {},
|
||||
}),
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
test('creates a local redeemed outcome for backdate requests without bridging back to backend', () => {
|
||||
const mockResult = createMockPromotionRedeemResult({
|
||||
context: {
|
||||
resolvePromotionRedeemSelection(accountNum, promotionId, promotionRuleId, outcomeIds, options) {
|
||||
assert.equal(accountNum, '800038008')
|
||||
assert.equal(promotionId, 71768004)
|
||||
assert.equal(promotionRuleId, 71768026)
|
||||
assert.deepEqual(outcomeIds, [71768072, 71768073])
|
||||
assert.deepEqual(options, { backdate: true })
|
||||
return {
|
||||
promotion: {
|
||||
code: 'LP-EE-CNYGS26',
|
||||
name: 'CNY Gift Set Earn & Get-2026',
|
||||
ruleName: 'CNYGS-188pts-Martell + LCH-Can Abalone',
|
||||
},
|
||||
selectedOutcomes: [
|
||||
{
|
||||
value: 'lp-ee-cnygs26-188pts-martellnoblige-me',
|
||||
prize: {
|
||||
prizeCode: 'lp-ee-cnygs26-188pts-martellnoblige-me',
|
||||
prizeCategory: 'PROMOTION',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: 'lp-ee-cnygs26-188pts-lchabalone-me',
|
||||
prize: {
|
||||
prizeCode: 'lp-ee-cnygs26-188pts-lchabalone-me',
|
||||
prizeCategory: 'PROMOTION',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
nextMockPromotionRedemptionId() {
|
||||
return 900001
|
||||
},
|
||||
generateToken(prefix) {
|
||||
return `${prefix}_001`
|
||||
},
|
||||
},
|
||||
requestBody: {
|
||||
schema: {},
|
||||
data: {
|
||||
accountNum: '800038008',
|
||||
promotionId: 71768004,
|
||||
promotionRuleId: 71768026,
|
||||
outcomeId: [71768072, 71768073],
|
||||
quantity: 1,
|
||||
backdate: '2026-03-23',
|
||||
},
|
||||
},
|
||||
accountNum: '800038008',
|
||||
backdate: true,
|
||||
})
|
||||
|
||||
assert.equal(mockResult.redeemedOutcome.redemptionId, 900001)
|
||||
assert.equal(mockResult.redeemedOutcome.promotionId, 71768004)
|
||||
assert.equal(mockResult.redeemedOutcome.prizeRuleId, 71768026)
|
||||
assert.equal(mockResult.redeemedOutcome.outcome.redeemedList.length, 2)
|
||||
assert.equal(
|
||||
mockResult.redeemedOutcome.outcome.redeemedList[0].transId,
|
||||
'mock_backdate_redemption_001',
|
||||
)
|
||||
})
|
||||
|
||||
test('bridges backdate requests to backend when promotion bridge is enabled', async (t) => {
|
||||
const originalFetch = global.fetch
|
||||
t.after(() => {
|
||||
global.fetch = originalFetch
|
||||
})
|
||||
|
||||
const fetchCalls = []
|
||||
global.fetch = async (url, options = {}) => {
|
||||
const parsedBody = options.body ? JSON.parse(options.body) : null
|
||||
fetchCalls.push({
|
||||
url,
|
||||
method: options.method,
|
||||
headers: options.headers,
|
||||
body: parsedBody,
|
||||
})
|
||||
|
||||
if (url === 'http://backend.test/api/v1/auth/login') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
text: async () => JSON.stringify({ success: true, data: { accessToken: 'token-123' } }),
|
||||
}
|
||||
}
|
||||
|
||||
if (url === 'http://backend.test/api/v1/prize-redemptions') {
|
||||
assert.equal(parsedBody.customerId, '80038008')
|
||||
assert.equal(parsedBody.metadata.redemption_id, 900002)
|
||||
assert.equal(parsedBody.metadata.promotion_id, 71768004)
|
||||
assert.equal(parsedBody.targetPrizes.length, 2)
|
||||
assert.deepEqual(
|
||||
parsedBody.targetPrizes.map((targetPrize) => targetPrize.issueTargetToWallet),
|
||||
[true, false],
|
||||
)
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
text: async () =>
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
data: {
|
||||
publicId: 'backend-redemption-001',
|
||||
overallStatus: 'COMPLETED',
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected fetch URL: ${url}`)
|
||||
}
|
||||
|
||||
const bridgeResult = await bridgePromotionRedeemToEwallet({
|
||||
context: {
|
||||
resolvePromotionRedeemSelection(accountNum, promotionId, promotionRuleId, outcomeIds, options) {
|
||||
assert.equal(accountNum, '80038008')
|
||||
assert.equal(promotionId, 71768004)
|
||||
assert.equal(promotionRuleId, 71768024)
|
||||
assert.deepEqual(outcomeIds, [71768070, 71768069])
|
||||
assert.deepEqual(options, { backdate: true })
|
||||
return {
|
||||
promotion: {
|
||||
code: 'LP-EE-CNYGS26',
|
||||
name: 'CNY Gift Set Earn & Get-2026',
|
||||
ruleName: 'CNYGS-188pts-Hennessy + LCH-Scallop',
|
||||
},
|
||||
selectedOutcomes: [
|
||||
{
|
||||
key: 71768070,
|
||||
value: 'lp-ee-cnygs26-188pts-lchscallop-me',
|
||||
prize: {
|
||||
prizeCode: 'lp-ee-cnygs26-188pts-lchscallop-me',
|
||||
prizeCategory: 'PROMOTION',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 71768069,
|
||||
value: 'lp-ee-cnygs26-188pts-hennessyvsop-me',
|
||||
prize: {
|
||||
prizeCode: 'lp-ee-cnygs26-188pts-hennessyvsop-me',
|
||||
prizeCategory: 'PROMOTION',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
nextMockPromotionRedemptionId() {
|
||||
return 900002
|
||||
},
|
||||
promotionRedemptionBridgeLoginUsername: 'mock.gateway',
|
||||
promotionRedemptionBridgeLoginPassword: 'secret',
|
||||
promotionRedemptionBridgeBaseUrl: 'http://backend.test',
|
||||
promotionRedemptionBridgeTimeoutMs: 5000,
|
||||
promotionRedemptionSourceBucket: 'POINT',
|
||||
promotionRedemptionInitiateSource: 'PROMOTION',
|
||||
generateToken(prefix) {
|
||||
return `${prefix}_001`
|
||||
},
|
||||
},
|
||||
requestBody: {
|
||||
schema: {
|
||||
computerName: 'BOH-DT200244',
|
||||
ipAddress: '10.20.30.40',
|
||||
transactionId: 'mock-backdate-request-001',
|
||||
},
|
||||
data: {
|
||||
accountNum: '80038008',
|
||||
promotionId: 71768004,
|
||||
promotionRuleId: 71768024,
|
||||
outcomeId: [71768070, 71768069],
|
||||
issueTargetToWallet: [true, false],
|
||||
quantity: 1,
|
||||
loginId: 'admin',
|
||||
casinoCode: 'GLP',
|
||||
locationCode: 'GLP01',
|
||||
backdate: '2026-04-21',
|
||||
},
|
||||
},
|
||||
accountNum: '80038008',
|
||||
backdate: true,
|
||||
})
|
||||
|
||||
assert.equal(bridgeResult.redeemedOutcome.redemptionId, 900002)
|
||||
assert.equal(bridgeResult.redeemedOutcome.outcome.redeemedList.length, 2)
|
||||
assert.equal(
|
||||
bridgeResult.redeemedOutcome.outcome.redeemedList[0].transId,
|
||||
'backend-redemption-001',
|
||||
)
|
||||
assert.equal(fetchCalls.length, 2)
|
||||
assert.equal(fetchCalls[0].url, 'http://backend.test/api/v1/auth/login')
|
||||
assert.equal(fetchCalls[1].url, 'http://backend.test/api/v1/prize-redemptions')
|
||||
})
|
||||
|
||||
test('header overrides are merged into request data for backend passthrough', () => {
|
||||
const normalizedRequestBody = mergeIssueTargetToWalletOverrides(
|
||||
{
|
||||
data: {
|
||||
outcomeId: [11330011, 11330012],
|
||||
},
|
||||
},
|
||||
{
|
||||
[ISSUE_TARGET_TO_WALLET_HEADER]: '{"11330011":false,"11330012":true}',
|
||||
},
|
||||
)
|
||||
|
||||
assert.deepEqual(normalizedRequestBody.data.issueTargetToWalletByOutcomeId, {
|
||||
'11330011': false,
|
||||
'11330012': true,
|
||||
})
|
||||
})
|
||||
|
||||
test('body overrides win over header overrides when both are present', () => {
|
||||
const normalizedRequestBody = mergeIssueTargetToWalletOverrides(
|
||||
{
|
||||
data: {
|
||||
issueTargetToWalletByOutcomeId: {
|
||||
'11330011': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
[ISSUE_TARGET_TO_WALLET_HEADER]: '{"11330011":false,"11330012":true}',
|
||||
},
|
||||
)
|
||||
|
||||
assert.deepEqual(normalizedRequestBody.data.issueTargetToWalletByOutcomeId, {
|
||||
'11330011': true,
|
||||
'11330012': true,
|
||||
})
|
||||
})
|
||||
|
||||
test('runtime overrides are merged for matching promotion outcomes', () => {
|
||||
const normalizedRequestBody = mergeRuntimeIssueTargetToWalletOverrides(
|
||||
{
|
||||
data: {
|
||||
promotionId: 11330,
|
||||
promotionRuleId: 1133001,
|
||||
outcomeId: [11330011, 11330012],
|
||||
},
|
||||
},
|
||||
{
|
||||
resolvePromotionRedeemFulfillmentOverrideByOutcomeId(input) {
|
||||
assert.deepEqual(input, {
|
||||
accountNum: '80010991',
|
||||
promotionId: 11330,
|
||||
promotionRuleId: 1133001,
|
||||
outcomeIds: [11330011, 11330012],
|
||||
})
|
||||
|
||||
return {
|
||||
'11330011': false,
|
||||
'11330012': true,
|
||||
}
|
||||
},
|
||||
},
|
||||
'80010991',
|
||||
)
|
||||
|
||||
assert.deepEqual(normalizedRequestBody.data.issueTargetToWalletByOutcomeId, {
|
||||
'11330011': false,
|
||||
'11330012': true,
|
||||
})
|
||||
})
|
||||
|
||||
test('request overrides still win over runtime overrides', () => {
|
||||
const normalizedRequestBody = mergeRuntimeIssueTargetToWalletOverrides(
|
||||
{
|
||||
data: {
|
||||
promotionId: 11330,
|
||||
promotionRuleId: 1133001,
|
||||
outcomeId: [11330011, 11330012],
|
||||
issueTargetToWalletByOutcomeId: {
|
||||
'11330011': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
resolvePromotionRedeemFulfillmentOverrideByOutcomeId() {
|
||||
return {
|
||||
'11330011': false,
|
||||
'11330012': false,
|
||||
}
|
||||
},
|
||||
},
|
||||
'80010991',
|
||||
)
|
||||
|
||||
assert.deepEqual(normalizedRequestBody.data.issueTargetToWalletByOutcomeId, {
|
||||
'11330011': true,
|
||||
'11330012': false,
|
||||
})
|
||||
})
|
||||
|
||||
test('defaults USER_CHOICE promotions to wallet when no explicit override is provided', () => {
|
||||
const resolved = resolveIssueTargetToWallet({
|
||||
requestData: {},
|
||||
outcome: {
|
||||
key: 11330011,
|
||||
prize: {
|
||||
deliveryMode: 'USER_CHOICE',
|
||||
},
|
||||
},
|
||||
index: 0,
|
||||
prizeIdentifier: null,
|
||||
})
|
||||
|
||||
assert.equal(resolved, true)
|
||||
})
|
||||
|
||||
test('uses non-empty gisPrizeIdentifier to resolve USER_CHOICE promotions as external', () => {
|
||||
const resolved = resolveIssueTargetToWallet({
|
||||
requestData: {},
|
||||
outcome: {
|
||||
key: 11330011,
|
||||
prize: {
|
||||
deliveryMode: 'USER_CHOICE',
|
||||
},
|
||||
},
|
||||
index: 0,
|
||||
prizeIdentifier: 'GIS-CODE-001',
|
||||
})
|
||||
|
||||
assert.equal(resolved, false)
|
||||
})
|
||||
|
||||
test('request outcome override takes precedence over delivery mode inference', () => {
|
||||
const resolved = resolveIssueTargetToWallet({
|
||||
requestData: {
|
||||
issueTargetToWalletByOutcomeId: {
|
||||
'11330011': false,
|
||||
},
|
||||
},
|
||||
outcome: {
|
||||
key: 11330011,
|
||||
prize: {
|
||||
deliveryMode: 'USER_CHOICE',
|
||||
},
|
||||
},
|
||||
index: 0,
|
||||
prizeIdentifier: null,
|
||||
})
|
||||
|
||||
assert.equal(resolved, false)
|
||||
})
|
||||
|
||||
test('fixture-level mockIssueTargetToWallet override is honored', () => {
|
||||
const resolved = resolveIssueTargetToWallet({
|
||||
requestData: {},
|
||||
outcome: {
|
||||
key: 11330011,
|
||||
mockIssueTargetToWallet: false,
|
||||
prize: {
|
||||
deliveryMode: 'USER_CHOICE',
|
||||
},
|
||||
},
|
||||
index: 0,
|
||||
prizeIdentifier: null,
|
||||
})
|
||||
|
||||
assert.equal(resolved, false)
|
||||
})
|
||||
|
||||
test('request array override is honored by outcome index', () => {
|
||||
const resolved = resolveIssueTargetToWallet({
|
||||
requestData: {
|
||||
issueTargetToWallet: [true, false],
|
||||
},
|
||||
outcome: {
|
||||
key: 11330012,
|
||||
prize: {
|
||||
deliveryMode: 'WALLET_ONLY',
|
||||
},
|
||||
},
|
||||
index: 1,
|
||||
prizeIdentifier: null,
|
||||
})
|
||||
|
||||
assert.equal(resolved, false)
|
||||
})
|
||||
|
||||
test('request array override can distinguish duplicate outcome ids by position', () => {
|
||||
const firstResolved = resolveIssueTargetToWallet({
|
||||
requestData: {
|
||||
issueTargetToWallet: [true, false, true],
|
||||
},
|
||||
outcome: {
|
||||
key: 11330011,
|
||||
prize: {
|
||||
deliveryMode: 'USER_CHOICE',
|
||||
},
|
||||
},
|
||||
index: 0,
|
||||
prizeIdentifier: null,
|
||||
})
|
||||
|
||||
const secondResolved = resolveIssueTargetToWallet({
|
||||
requestData: {
|
||||
issueTargetToWallet: [true, false, true],
|
||||
},
|
||||
outcome: {
|
||||
key: 11330011,
|
||||
prize: {
|
||||
deliveryMode: 'USER_CHOICE',
|
||||
},
|
||||
},
|
||||
index: 1,
|
||||
prizeIdentifier: null,
|
||||
})
|
||||
|
||||
assert.equal(firstResolved, true)
|
||||
assert.equal(secondResolved, false)
|
||||
})
|
||||
Reference in New Issue
Block a user