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:
@@ -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=true(Ctrl+V 的 keyCode=86,ctrlKey=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);
|
||||
});
|
||||
});
|
||||
Generated
+4681
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user