feat(ai): add expense application feedback ledger
This commit is contained in:
140
web/tests/expense-application-decision-feedback.test.mjs
Normal file
140
web/tests/expense-application-decision-feedback.test.mjs
Normal file
@@ -0,0 +1,140 @@
|
||||
import assert from 'node:assert/strict'
|
||||
|
||||
import { trackApplicationPreviewFieldEdit } from '../src/utils/expenseApplicationDecisionFeedback.js'
|
||||
|
||||
function testTracksFirstExplicitEdit() {
|
||||
const previous = {
|
||||
fields: {
|
||||
reason: '客户拜访',
|
||||
location: '上海'
|
||||
}
|
||||
}
|
||||
const next = {
|
||||
...previous,
|
||||
fields: {
|
||||
...previous.fields,
|
||||
reason: '客户现场实施'
|
||||
}
|
||||
}
|
||||
|
||||
const tracked = trackApplicationPreviewFieldEdit(previous, next, 'reason')
|
||||
|
||||
assert.deepEqual(tracked.aiDecisionFeedback.changedFields, [
|
||||
{
|
||||
fieldKey: 'reason',
|
||||
suggestedValue: '客户拜访',
|
||||
finalValue: '客户现场实施'
|
||||
}
|
||||
])
|
||||
assert.equal(tracked.aiDecisionFeedback.revision, 1)
|
||||
}
|
||||
|
||||
function testKeepsOriginalSuggestionAcrossRepeatedEdits() {
|
||||
const first = trackApplicationPreviewFieldEdit(
|
||||
{ fields: { transportMode: '火车' } },
|
||||
{ fields: { transportMode: '飞机' } },
|
||||
'transportMode'
|
||||
)
|
||||
const second = trackApplicationPreviewFieldEdit(
|
||||
first,
|
||||
{ ...first, fields: { transportMode: '自驾' } },
|
||||
'transportMode'
|
||||
)
|
||||
|
||||
assert.deepEqual(second.aiDecisionFeedback.changedFields, [
|
||||
{
|
||||
fieldKey: 'transportMode',
|
||||
suggestedValue: '火车',
|
||||
finalValue: '自驾'
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
function testRemovesDiffWhenUserRestoresSuggestion() {
|
||||
const edited = trackApplicationPreviewFieldEdit(
|
||||
{ fields: { location: '上海' } },
|
||||
{ fields: { location: '北京' } },
|
||||
'location'
|
||||
)
|
||||
const restored = trackApplicationPreviewFieldEdit(
|
||||
edited,
|
||||
{ ...edited, fields: { location: '上海' } },
|
||||
'location'
|
||||
)
|
||||
|
||||
assert.deepEqual(restored.aiDecisionFeedback.changedFields, [])
|
||||
}
|
||||
|
||||
function testReturnDateUsesCanonicalTimeField() {
|
||||
const tracked = trackApplicationPreviewFieldEdit(
|
||||
{ fields: { time: '2026-07-20 至 2026-07-22' } },
|
||||
{ fields: { time: '2026-07-20 至 2026-07-24' } },
|
||||
'time_return'
|
||||
)
|
||||
|
||||
assert.equal(tracked.aiDecisionFeedback.changedFields[0].fieldKey, 'time')
|
||||
}
|
||||
|
||||
function testTracksDateAndDerivedDaysTogether() {
|
||||
const previous = {
|
||||
fields: {
|
||||
time: '2026-02-20 至 2026-02-23',
|
||||
days: '4天'
|
||||
}
|
||||
}
|
||||
const next = {
|
||||
fields: {
|
||||
time: '2026-02-20 至 2026-02-24',
|
||||
days: '5天'
|
||||
}
|
||||
}
|
||||
|
||||
const tracked = trackApplicationPreviewFieldEdit(
|
||||
previous,
|
||||
next,
|
||||
['time_return', 'days']
|
||||
)
|
||||
|
||||
assert.deepEqual(tracked.aiDecisionFeedback.changedFields, [
|
||||
{ fieldKey: 'days', suggestedValue: '4天', finalValue: '5天' },
|
||||
{
|
||||
fieldKey: 'time',
|
||||
suggestedValue: '2026-02-20 至 2026-02-23',
|
||||
finalValue: '2026-02-20 至 2026-02-24'
|
||||
}
|
||||
])
|
||||
assert.equal(tracked.aiDecisionFeedback.revision, 1)
|
||||
|
||||
const editedAgain = trackApplicationPreviewFieldEdit(
|
||||
tracked,
|
||||
{
|
||||
...tracked,
|
||||
fields: {
|
||||
time: '2026-02-20 至 2026-02-25',
|
||||
days: '6天'
|
||||
}
|
||||
},
|
||||
['time', 'days']
|
||||
)
|
||||
assert.equal(editedAgain.aiDecisionFeedback.changedFields[0].suggestedValue, '4天')
|
||||
assert.equal(
|
||||
editedAgain.aiDecisionFeedback.changedFields[1].suggestedValue,
|
||||
'2026-02-20 至 2026-02-23'
|
||||
)
|
||||
assert.equal(editedAgain.aiDecisionFeedback.revision, 2)
|
||||
|
||||
const restored = trackApplicationPreviewFieldEdit(
|
||||
editedAgain,
|
||||
{ ...editedAgain, fields: previous.fields },
|
||||
['time', 'days']
|
||||
)
|
||||
assert.deepEqual(restored.aiDecisionFeedback.changedFields, [])
|
||||
assert.equal(restored.aiDecisionFeedback.revision, 3)
|
||||
}
|
||||
|
||||
testTracksFirstExplicitEdit()
|
||||
testKeepsOriginalSuggestionAcrossRepeatedEdits()
|
||||
testRemovesDiffWhenUserRestoresSuggestion()
|
||||
testReturnDateUsesCanonicalTimeField()
|
||||
testTracksDateAndDerivedDaysTogether()
|
||||
console.log('expense-application-decision-feedback tests passed')
|
||||
Reference in New Issue
Block a user