Files
EasyCLIProxyAPI/tests/operationFeedback.test.ts
T
lzt404 18c285a810 fix(ui): unify action feedback and improve localization
- Replace transient toasts with dismissible, accessible inline notices
- Remove redundant success messages for toggles and clipboard actions
- Preserve list focus during background refreshes
- Remove duplicate English captions and localize onboarding content
- Complete Japanese translations and remove English fallback
- Preserve API field names, Token units, and raw reasoning-level values
- Add regression tests for operation feedback and localization
2026-09-07 01:13:45 +08:00

71 lines
2.9 KiB
TypeScript

import { describe, expect, it } from 'bun:test';
import { readFileSync } from 'node:fs';
import ts from 'typescript';
function actionCalls(file: string, action: string, callback: string) {
const source = ts.createSourceFile(
file,
readFileSync(new URL(`../src/pages/${file}`, import.meta.url), 'utf8'),
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TSX,
);
const calls: ts.CallExpression[] = [];
let found = false;
const visitAction = (node: ts.Node) => {
if (ts.isCallExpression(node) && node.expression.getText(source) === callback) calls.push(node);
ts.forEachChild(node, visitAction);
};
const visit = (node: ts.Node) => {
if (ts.isVariableDeclaration(node) && node.name.getText(source) === action && node.initializer) {
found = true;
visitAction(node.initializer);
} else {
ts.forEachChild(node, visit);
}
};
visit(source);
expect(found).toBe(true);
return { source, calls };
}
describe('控件自身反馈', () => {
it('API 开关只报告失败,不再为成功切换插入额外消息', () => {
const { calls } = actionCalls('ApiAccessPage.tsx', 'toggleProvider', 'setNotice');
const nonEmptyCalls = calls.filter((call) => !ts.isStringLiteral(call.arguments[0]) || call.arguments[0].text !== '');
expect(nonEmptyCalls).toHaveLength(1);
expect(nonEmptyCalls[0].arguments[1].getText()).toBe("'error'");
});
it('认证文件的启用停用由按钮与状态标签反馈', () => {
expect(actionCalls('AuthFileManagementPage.tsx', 'toggleStatus', 'showNotice').calls).toHaveLength(0);
});
it('开关切换只后台刷新数据,不卸载整张列表和焦点控件', () => {
for (const [file, action, callback] of [
['ApiAccessPage.tsx', 'toggleProvider', 'loadProviders'],
['AuthFileManagementPage.tsx', 'toggleStatus', 'loadFiles'],
]) {
const { calls } = actionCalls(file, action, callback);
expect(calls).toHaveLength(1);
expect(calls[0].arguments[0]?.getText()).toBe('false');
}
});
it('复制密钥仅保留原按钮勾选和失败提示', () => {
const { calls } = actionCalls('ConfigPanel.tsx', 'copyApiKey', 'keyFeedback.showNotice');
expect(calls).toHaveLength(1);
expect(calls[0].arguments[1].getText()).toBe("'error'");
});
it('首页启动和停止不重复报成功,只有重启需要额外结果', () => {
const { source, calls } = actionCalls('Kernel.tsx', 'runCoreProcessCommand', 'showProcessNotice');
const successCalls = calls.filter((call) => call.arguments[1]?.getText(source) === "'success'");
expect(successCalls).toHaveLength(1);
let ancestor: ts.Node | undefined = successCalls[0].parent;
while (ancestor && !ts.isIfStatement(ancestor)) ancestor = ancestor.parent;
expect(ancestor && ts.isIfStatement(ancestor) ? ancestor.expression.getText(source) : '')
.toBe("command === 'restart_core_process'");
});
});