Files
zszq-trs/YLErpWeb/fe-tests/main.postSafe.test.js

145 lines
5.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* main.postSafe.test.js — main.postSafe() 错误守卫封装测试
* ============================================================================
* 目的:验证 postSafe 正确将 jQuery Deferred 的 .done/.fail 映射到 Promise 的 resolve/reject
* 防止「业务错误走 reject、.done 不触发」陷阱复发。
*
* 覆盖场景:
* 1. 成功请求 → Promise resolve
* 2. 业务错误(resp.success === false)→ Promise reject
* 3. 网络异常 → Promise reject
* 4. async/await 语法兼容性
* 5. 与 main.post 行为对比(陷阱复现)
*
* 运行:cd YLErpWeb/fe-tests && npx jest main.postSafe
* ============================================================================
*/
// 搭建最小 DOM 环境
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;
// Mock main 对象(与 main.js 中的逻辑等价)
var main = {};
// main.post: 返回 jQuery Deferred promise,测试中通过 _lastDeferred 控制结果
main.post = function (url, data, options) {
var doneCb = [], failCb = [];
var promise = {
done: function (cb) { doneCb.push(cb); return promise; },
fail: function (cb) { failCb.push(cb); return promise; },
};
main._lastDeferred = {
resolve: function (resp) { doneCb.forEach(function (cb) { cb(resp); }); },
reject: function (resp) { failCb.forEach(function (cb) { cb(resp); }); },
promise: function () { return promise; },
};
return main._lastDeferred.promise();
};
// main.postSafe: 与 main.js 中完全相同的实现
main.postSafe = function (url, data, options) {
return new Promise(function (resolve, reject) {
main.post(url, data, options)
.done(function (resp) { resolve(resp); })
.fail(function (resp) { reject(resp); });
});
};
describe('main.postSafe — Promise 封装守卫', function () {
test('成功请求 → Promise resolve(resp)', function () {
var p = main.postSafe('/api/test', { foo: 1 });
// postSafe 内部已调用 main.post_lastDeferred 已就绪
main._lastDeferred.resolve({ success: true, data: 'ok' });
return p.then(function (resp) {
expect(resp.success).toBe(true);
expect(resp.data).toBe('ok');
});
});
test('业务错误(resp.success===false)→ Promise reject(resp)', function () {
var p = main.postSafe('/api/test', { foo: 1 });
main._lastDeferred.reject({ success: false, msg: '算不出来' });
return p.catch(function (resp) {
expect(resp.success).toBe(false);
expect(resp.msg).toBe('算不出来');
});
});
test('网络异常 → Promise reject', function () {
var p = main.postSafe('/api/test', { foo: 1 });
main._lastDeferred.reject({ errcode: 500, msg: '请求失败' });
return p.catch(function (resp) {
expect(resp.errcode).toBe(500);
});
});
test('async/await 语法兼容 — 成功路径', async function () {
var p = main.postSafe('/api/test', { foo: 1 });
main._lastDeferred.resolve({ success: true, value: 42 });
var resp = await p;
expect(resp.success).toBe(true);
expect(resp.value).toBe(42);
});
test('async/await 语法兼容 — 失败路径', async function () {
var p = main.postSafe('/api/test', { foo: 1 });
main._lastDeferred.reject({ success: false, msg: '计算失败' });
var caught = null;
try {
await p;
} catch (resp) {
caught = resp;
}
expect(caught).not.toBeNull();
expect(caught.success).toBe(false);
expect(caught.msg).toBe('计算失败');
});
});
describe('main.postSafe — 与 main.post 行为对比(陷阱复现)', function () {
test('main.post 的 .done 在业务错误时不触发(陷阱复现)', function () {
var doneCalled = false;
var failCalled = false;
main.post('/api/test', {}).done(function () {
doneCalled = true;
}).fail(function () {
failCalled = true;
});
// 业务错误 → reject
main._lastDeferred.reject({ success: false });
expect(doneCalled).toBe(false); // .done 没触发!这就是陷阱
expect(failCalled).toBe(true); // .fail 触发了
});
test('main.postSafe 的 .then 在业务错误时不触发(安全)', function () {
var thenCalled = false;
var caught = null;
var p = main.postSafe('/api/test', {}).then(function () {
thenCalled = true;
}).catch(function (resp) {
caught = resp;
});
// 业务错误 → reject
main._lastDeferred.reject({ success: false, msg: 'biz error' });
// Promise 是微任务,需要等一轮
return p.then(function () {
expect(thenCalled).toBe(false); // .then 没触发
expect(caught).not.toBeNull(); // .catch 触发了
expect(caught.msg).toBe('biz error');
});
});
});