200 lines
6.2 KiB
JavaScript
200 lines
6.2 KiB
JavaScript
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const fs = require('node:fs')
|
|
const os = require('node:os')
|
|
const path = require('node:path')
|
|
|
|
const { createMockContext } = require('../src/context/createMockContext')
|
|
|
|
function withEnv(overrides, fn) {
|
|
const previousValues = new Map()
|
|
|
|
for (const [key, value] of Object.entries(overrides)) {
|
|
previousValues.set(key, process.env[key])
|
|
if (value === undefined) {
|
|
delete process.env[key]
|
|
} else {
|
|
process.env[key] = value
|
|
}
|
|
}
|
|
|
|
try {
|
|
return fn()
|
|
} finally {
|
|
for (const [key, value] of previousValues.entries()) {
|
|
if (value === undefined) {
|
|
delete process.env[key]
|
|
} else {
|
|
process.env[key] = value
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
test('uses a timestamp seed when MOCK_PROMOTION_REDEMPTION_ID_START is unset', () =>
|
|
withEnv(
|
|
{
|
|
MOCK_PROMOTION_REDEMPTION_ID_START: undefined,
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'false',
|
|
},
|
|
() => {
|
|
const originalDateNow = Date.now
|
|
Date.now = () => 1760000000123
|
|
|
|
try {
|
|
const context = createMockContext()
|
|
assert.equal(context.nextMockPromotionRedemptionId(), 1760000000)
|
|
assert.equal(context.nextMockPromotionRedemptionId(), 1760000001)
|
|
} finally {
|
|
Date.now = originalDateNow
|
|
}
|
|
},
|
|
))
|
|
|
|
test('falls back to an int-safe timestamp seed when configured redemption id start is out of range', () =>
|
|
withEnv(
|
|
{
|
|
MOCK_PROMOTION_REDEMPTION_ID_START: '1774243846923',
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'false',
|
|
},
|
|
() => {
|
|
const originalDateNow = Date.now
|
|
Date.now = () => 1760000000123
|
|
|
|
try {
|
|
const context = createMockContext()
|
|
assert.equal(context.nextMockPromotionRedemptionId(), 1760000000)
|
|
} finally {
|
|
Date.now = originalDateNow
|
|
}
|
|
},
|
|
))
|
|
|
|
test('fallback redeemed promotion detail consumes the same incrementing redemption id sequence', () =>
|
|
withEnv(
|
|
{
|
|
MOCK_PROMOTION_REDEMPTION_ID_START: '910000',
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'false',
|
|
},
|
|
() => {
|
|
const context = createMockContext()
|
|
|
|
const firstOutcome = context.buildMockRedeemedPromotionOutcome({
|
|
data: { loginId: 'tester' },
|
|
schema: {},
|
|
})
|
|
const secondOutcome = context.buildMockRedeemedPromotionOutcome({
|
|
data: { loginId: 'tester' },
|
|
schema: {},
|
|
})
|
|
|
|
assert.equal(firstOutcome.redemptionId, 910000)
|
|
assert.equal(secondOutcome.redemptionId, 910001)
|
|
},
|
|
))
|
|
|
|
test('uses the birthday promotion fixture as the default promotion source when no override is configured', () =>
|
|
withEnv(
|
|
{
|
|
MOCK_PROMOTION_CAPTURE_FILE: undefined,
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'false',
|
|
},
|
|
() => {
|
|
const context = createMockContext()
|
|
const promotions = context.getPromotionLists('910700001')
|
|
|
|
assert.equal(promotions.eligiblePromotionList.length, 1)
|
|
assert.equal(promotions.eligiblePromotionList[0].code, 'PROMO-BIRTHDAY-2026')
|
|
assert.equal(promotions.eligiblePromotionList[0].ruleId, 3800801)
|
|
assert.equal(promotions.eligiblePromotionList[0].outcomeList.length, 3)
|
|
assert.equal(promotions.eligiblePromotionList[0].isEntitled, true)
|
|
},
|
|
))
|
|
|
|
test('backdate promotions returned by the fixed fixture satisfy the frontend redeemable contract', () =>
|
|
withEnv(
|
|
{
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'false',
|
|
},
|
|
() => {
|
|
const context = createMockContext()
|
|
const promotions = context.getBackdatePromotionLists('800038008')
|
|
|
|
assert.ok(promotions.entitledPromotionList.length > 0)
|
|
promotions.entitledPromotionList.forEach((item) => {
|
|
assert.equal(item.isEntitled, true)
|
|
assert.equal(item.isRedeemCompleted, false)
|
|
assert.ok(Number(item.awardsEntitled) > Number(item.awardsCount))
|
|
})
|
|
},
|
|
))
|
|
|
|
test('backdate promotions can be resolved through the default 80038008 member alias', () =>
|
|
withEnv(
|
|
{
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'false',
|
|
},
|
|
() => {
|
|
const context = createMockContext()
|
|
const promotions = context.getBackdatePromotionLists('80038008')
|
|
|
|
assert.ok(promotions.entitledPromotionList.length > 0)
|
|
assert.equal(promotions.entitledPromotionList[0].ruleId, 3800801)
|
|
assert.equal(promotions.entitledPromotionList[0].isEntitled, true)
|
|
},
|
|
))
|
|
|
|
test('persists runtime recorded redeemed promotions and resumes redemption id sequence', () => {
|
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mock-gateway-recording-'))
|
|
const recordingFile = path.join(tempDir, 'redeemed-promotions.recorded.json')
|
|
|
|
try {
|
|
withEnv(
|
|
{
|
|
MOCK_PROMOTION_REDEMPTION_ID_START: '910000',
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_ENABLED: 'true',
|
|
MOCK_REDEEMED_PROMOTION_RECORDING_FILE: recordingFile,
|
|
},
|
|
() => {
|
|
const firstContext = createMockContext()
|
|
firstContext.recordRedeemedPromotionOutcome('80010991', {
|
|
redemptionId: 910005,
|
|
promotionId: 11225,
|
|
outcome: {
|
|
redeemedList: [
|
|
{
|
|
outcomeRemark: 'qa-ebonus-auto',
|
|
transId: 'tx-910005',
|
|
},
|
|
],
|
|
},
|
|
})
|
|
|
|
const persisted = JSON.parse(fs.readFileSync(recordingFile, 'utf8'))
|
|
assert.equal(persisted.accounts['80010991'][0].redemptionId, 910005)
|
|
|
|
const secondContext = createMockContext()
|
|
assert.equal(secondContext.getRecordedRedeemedPromotionOutcomes('80010991')[0].redemptionId, 910005)
|
|
assert.equal(secondContext.nextMockPromotionRedemptionId(), 910006)
|
|
},
|
|
)
|
|
} finally {
|
|
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
test('account-specific redeemed promotions fixture preserves voidedByEmployeeId for the 2026-04-06 voided record', () => {
|
|
const context = createMockContext()
|
|
const fixture = context.getAccountSpecificRedeemedPromotionsFixture('100000059')
|
|
|
|
const targetOutcome = fixture.data.outcomeList.find(
|
|
(item) =>
|
|
item.voidedDtm === '2026-04-06T16:11:05.584548' &&
|
|
item.outcome?.redeemedList?.[0]?.transId === '43a9ab81-bbff-4812-bd64-bfd4eaa50d72',
|
|
)
|
|
|
|
assert.ok(targetOutcome)
|
|
assert.equal(targetOutcome.voidedBy, 'qa-randyng')
|
|
assert.equal(targetOutcome.voidedByEmployeeId, '171853')
|
|
})
|