初始化
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
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')
|
||||
})
|
||||
Reference in New Issue
Block a user