Merge branch 'refs/heads/glms/feature/1.4.2' into glms/feature/dotnumber
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* swapPriceInput.component.test.js — vue-swap-price-input 事件派发回归守卫
|
||||
* ============================================================================
|
||||
* 目的:锁定债券三字段输入组件「粘贴 / 重输原值 不派发 input/enter」的 bug。
|
||||
* 症状:粘贴或重输原值后,点空白(标REV/清其他标识)与回车(触发计算)均无反应。
|
||||
* 根因:组件把 input/enter 全部锁在原生 change 事件里,而 change 仅在「值相对聚焦时
|
||||
* 变动」才触发;onPaste 甚至完全不派发任何事件。
|
||||
*
|
||||
* 做法:直接实例化组件 options 对象(createVueInputComponent),用 mock this + $emit 间谍
|
||||
* 驱动 onPaste/onKeydown/onChange,断言事件派发。不依赖 Vue 运行时挂载、不改动源文件。
|
||||
*
|
||||
* 运行:cd YLErpWeb/fe-tests && npx jest swapPriceInput.component
|
||||
* 设 SWAP_PRICE_HELPER 指向其它版本文件可做对照(如改之前的旧代码应使用例变红)。
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function loadComponent() {
|
||||
const rel = process.env.SWAP_PRICE_HELPER
|
||||
|| '../wwwroot/Scripts/app/swaptrade/swapPricePrecisionHelper.js';
|
||||
const file = path.resolve(__dirname, rel);
|
||||
const code = fs.readFileSync(file, 'utf8');
|
||||
// swapPricePrecisionHelper.js: var swapPricePrecision = (function(global){...})(window);
|
||||
// 在受控作用域求值并取出 createVueInputComponent(IIFE 不挂 window,故用 new Function 取返回值)。
|
||||
const factory = new Function('window', 'global', 'console', code + '\n;return swapPricePrecision;');
|
||||
const sandbox = {};
|
||||
const swapPricePrecision = factory(sandbox, sandbox, console);
|
||||
return swapPricePrecision.createVueInputComponent();
|
||||
}
|
||||
|
||||
function makeCtx(component, opts) {
|
||||
opts = opts || {};
|
||||
const emitted = [];
|
||||
const ctx = {
|
||||
text: opts.text != null ? String(opts.text) : '',
|
||||
enterPressed: false,
|
||||
formatSnapshot: '{}',
|
||||
format: opts.format || { integerDigits: 2, precision: 4, percent: true },
|
||||
$emit: function (name, payload) { emitted.push({ name: name, payload: payload }); },
|
||||
};
|
||||
Object.keys(component.methods).forEach(function (m) {
|
||||
ctx[m] = component.methods[m].bind(ctx);
|
||||
});
|
||||
return { ctx: ctx, emitted: emitted };
|
||||
}
|
||||
|
||||
describe('vue-swap-price-input 事件派发(粘贴 / 重输原值场景)', () => {
|
||||
const component = loadComponent();
|
||||
|
||||
test('粘贴原值应派发 input(点空白标REV / 清其他标识)', () => {
|
||||
const { ctx, emitted } = makeCtx(component, { text: '3.5', format: { integerDigits: 2, precision: 4, percent: true } });
|
||||
const evt = { preventDefault() {}, clipboardData: { getData: () => '3.5' }, target: { value: '' } };
|
||||
ctx.onPaste(evt);
|
||||
const inputs = emitted.filter(e => e.name === 'input');
|
||||
expect(inputs.length).toBe(1);
|
||||
expect(inputs[0].payload).toBe('0.035'); // percent:true → ÷100
|
||||
});
|
||||
|
||||
test('回车(原值未变)应派发 enter(触发自动计算)', () => {
|
||||
const { ctx, emitted } = makeCtx(component, { text: '3.5', format: { integerDigits: 2, precision: 4, percent: true } });
|
||||
const evt = { which: 13, keyCode: 13, key: 'Enter', target: { blur() {}, value: '3.5' } };
|
||||
ctx.onKeydown(evt);
|
||||
const enters = emitted.filter(e => e.name === 'enter');
|
||||
expect(enters.length).toBe(1);
|
||||
expect(enters[0].payload).toBe('0.035');
|
||||
});
|
||||
|
||||
test('回车(值已改)应派发 input+enter 各一次,且不重复派发 enter', () => {
|
||||
const { ctx, emitted } = makeCtx(component, { text: '3.6', format: { percent: true } });
|
||||
const evt = { which: 13, keyCode: 13, key: 'Enter', target: { blur() {}, value: '3.6' } };
|
||||
ctx.onKeydown(evt);
|
||||
expect(emitted.filter(e => e.name === 'input').length).toBe(1);
|
||||
expect(emitted.filter(e => e.name === 'enter').length).toBe(1);
|
||||
});
|
||||
|
||||
test('非 Enter 按键不应派发 enter / input', () => {
|
||||
const { ctx, emitted } = makeCtx(component, { text: '3.5', format: { percent: true } });
|
||||
const evt = { which: 65, keyCode: 65, key: 'a', target: { blur() {} } };
|
||||
ctx.onKeydown(evt);
|
||||
expect(emitted.filter(e => e.name === 'enter').length).toBe(0);
|
||||
expect(emitted.filter(e => e.name === 'input').length).toBe(0);
|
||||
});
|
||||
|
||||
test('失焦(onChange)即使值未变也应派发 input(点空白标REV),且不再派发 enter', () => {
|
||||
const { ctx, emitted } = makeCtx(component, { text: '3.5', format: { percent: true } });
|
||||
const evt = { target: { value: '3.5' } };
|
||||
ctx.onChange(evt);
|
||||
expect(emitted.filter(e => e.name === 'input').length).toBe(1);
|
||||
expect(emitted.filter(e => e.name === 'enter').length).toBe(0);
|
||||
});
|
||||
|
||||
test('粘贴但格式为 percent:false 也应派发 input(原值透传)', () => {
|
||||
const { ctx, emitted } = makeCtx(component, { text: '3.5', format: { integerDigits: 2, precision: 4, percent: false } });
|
||||
const evt = { preventDefault() {}, clipboardData: { getData: () => '3.5' }, target: { value: '' } };
|
||||
ctx.onPaste(evt);
|
||||
expect(emitted.filter(e => e.name === 'input').length).toBe(1);
|
||||
expect(emitted.filter(e => e.name === 'input')[0].payload).toBe('3.5');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user