fix(fast): 修复 numberInput 粘贴路径 percent 字段 ×100,并补 Jest 粘贴回归单测

- fastVue.base.js: __onInput 粘贴分支原把显示值当模型值传入 setValue 导致 percent 字段 ×100;
  改为按 __change 同款口径先解析为模型值再回显,键盘输入路径不变
- 新增 numberInput.paste.test.js 覆盖 percent:true/append:%/append:‱/普通数字 4 类字段的 Ctrl+V 粘贴
- fe-tests package.json 增加 jest-environment-jsdom、jquery 依赖
This commit is contained in:
hjhan
2026-07-15 10:18:26 +08:00
parent 24b43d535e
commit ea313dc1c6
4 changed files with 4798 additions and 2 deletions
+105
View File
@@ -0,0 +1,105 @@
/**
* numberInput.paste.test.js — FastVue.numberInput 粘贴路径回归守卫
* ============================================================================
* 目的:防止 #EQD-5914 后新增的 `percent:true`+空 append 格式在粘贴时 ×100。
* 覆盖字段类型:percent、append:'%'、append:'‱'、普通数字。
*
* 运行:cd YLErpWeb/fe-tests && npm test -- numberInput.paste
*/
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
global.window = dom.window;
global.document = dom.window.document;
global.navigator = dom.window.navigator;
// fastVue.base.js 内部多个 IIFE 通过全局 FastVue 共享;
// 浏览器里 window.FastVue 与全局 FastVue 等价,Node 里需要桥接一下。
Object.defineProperty(global, 'FastVue', {
get() { return global.window.FastVue; },
set(value) { global.window.FastVue = value; },
configurable: true
});
const $ = require('jquery');
global.$ = $;
global.jQuery = $;
// fastVue.base.js 依赖全局 main.formatNumber
global.main = {
formatNumber: function (number, precision, options) {
const n = Number(number);
if (Number.isNaN(n)) return '0';
const useGrouping = options && options.grouping;
if (useGrouping) {
return n.toLocaleString('en-US', { minimumFractionDigits: precision, maximumFractionDigits: precision });
}
return n.toFixed(precision);
}
};
require('../wwwroot/Scripts/fast/fastVue.base.js');
function createInput() {
return document.createElement('input');
}
function simulatePaste(el, pastedText) {
el.value = pastedText;
// 先触发 keydown 让 _ctrlV=trueCtrl+V 的 keyCode=86ctrlKey=true
const keydown = new window.KeyboardEvent('keydown', { keyCode: 86, ctrlKey: true, bubbles: true });
el.dispatchEvent(keydown);
// 再触发 input 事件
const input = new window.Event('input', { bubbles: true });
el.dispatchEvent(input);
// 最后触发 change 事件(浏览器在失焦或回车时触发;这里手动触发验证 onchange)
const change = new window.Event('change', { bubbles: true });
el.dispatchEvent(change);
}
describe('FastVue.numberInput 粘贴路径', () => {
test('percent:true + 空 append:粘贴 99.07 不应 ×100(债券净价 bug 场景)', () => {
const el = createInput();
const changes = [];
FastVue.numberInput(el, { precision: 4, percent: true, append: '', onchange: (v) => changes.push(v) });
simulatePaste(el, '99.0756');
expect(el.value).toBe('99.0756');
expect(changes.length).toBeGreaterThan(0);
expect(changes[changes.length - 1]).toBeCloseTo(0.990756, 8);
});
test('append:"%":粘贴 99.07% 应解析为 0.9907', () => {
const el = createInput();
const changes = [];
FastVue.numberInput(el, { precision: 2, append: '%', onchange: (v) => changes.push(v) });
simulatePaste(el, '99.07%');
expect(el.value).toBe('99.07%');
expect(changes[changes.length - 1]).toBeCloseTo(0.9907, 8);
});
test('append:"‱":粘贴 990.7‱ 应解析为 0.09907', () => {
const el = createInput();
const changes = [];
FastVue.numberInput(el, { precision: 4, append: '‱', onchange: (v) => changes.push(v) });
simulatePaste(el, '990.7‱');
expect(el.value).toBe('990.7‱');
expect(changes[changes.length - 1]).toBeCloseTo(0.09907, 8);
});
test('普通数字字段:粘贴 99.07 保持原值', () => {
const el = createInput();
const changes = [];
FastVue.numberInput(el, { precision: 2, onchange: (v) => changes.push(v) });
simulatePaste(el, '99.07');
expect(el.value).toBe('99.07');
expect(changes[changes.length - 1]).toBeCloseTo(99.07, 8);
});
});
+4681
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -7,6 +7,8 @@
"test": "jest"
},
"devDependencies": {
"jest": "^29.7.0"
"jest": "^29.7.0",
"jest-environment-jsdom": "^30.4.1",
"jquery": "^4.0.0"
}
}
@@ -432,7 +432,15 @@
function __onInput() {
if (_ctrlV) {
_ctrlV = false;
return setValue(this.value);
// 粘贴进来的是显示值(可能带 %/‱ 后缀),先按 __change 同款口径解析为模型值再回显,
// 避免 setValue 把显示值再乘以 100/10000#EQD-5914 债券价格粘贴 ×100
let f = '';
if (this.value && this.value !== _options.append) {
f = parseFloat(this.value.replaceAll(",", "")) || 0;
if (_options.append === '%' || _options.percent == true) f /= 100;
else if (_options.append === '‱') f /= 10000;
}
return setValue(f);
}
if (_chnInput >= 0) {
__onChineseInput.call(this, _chnInput);