保留首页创建失败的安全正文

展示脱敏后的 IPC、Provider 与宿主失败原因

补充首页创建错误正文回归测试
This commit is contained in:
kdletters
2026-10-05 17:04:18 +08:00
parent cb42e46f0f
commit d9802bfa22
2 changed files with 34 additions and 8 deletions
@@ -11,6 +11,8 @@
* 落回本模块的专用兜底,并按「工作区是否已经建好」分成两条,避免用户重做一遍。
*/
import { visibleClientErrorMessage } from '../../services/errorReporting';
/** 未分类失败的专用兜底文案。 */
export const HOME_CREATION_UNCLASSIFIED_FAILURE = '创建未完成,请重试';
@@ -64,6 +66,19 @@ function isHomeCreationTransportText(text: string): boolean {
);
}
function safeHomeCreationDetail(error: unknown, code?: string) {
const detail = visibleClientErrorMessage(error, '').trim();
if (!detail) return '';
if (!code) return detail;
const withoutCode = detail
.replace(code, '')
.replace(/^\s*[::;;,,-]\s*/u, '')
.trim();
return withoutCode === code || /[::;;,,-]\s*$/u.test(withoutCode)
? ''
: withoutCode;
}
/**
* 由宿主错误算出用户可见文案。
*
@@ -76,20 +91,25 @@ export function homeCreationFailureMessage(
): string {
const projectCreated = options.projectCreated === true;
const text = homeCreationDiagnosticText(error);
const safeDetail = safeHomeCreationDetail(error);
if (isHomeCreationTransportText(text)) {
return projectCreated
const base = projectCreated
? HOME_CREATION_AFTER_PROJECT_IPC_FAILURE
: HOME_CREATION_IPC_FAILURE;
return safeDetail ? `${base}(${safeDetail})` : base;
}
const code = HOME_CREATION_HOST_CODE.exec(text)?.[0];
if (code) {
return projectCreated
const base = projectCreated
? `工作区已创建;未能进入项目开发(${code});请从「已创建的工作区」打开后重试。`
: `创建未完成(${code});请重试。`;
const detail = safeHomeCreationDetail(error, code);
return detail ? `${base}(${detail})` : base;
}
return projectCreated
const base = projectCreated
? HOME_CREATION_AFTER_PROJECT_FAILURE
: HOME_CREATION_UNCLASSIFIED_FAILURE;
return safeDetail ? `${base}(${safeDetail})` : base;
}
/** 包装成带证据的创建失败;控制器负责把 `diagnostic` 写进日志后再抛出。 */
@@ -28,7 +28,7 @@ it('宿主机器码原样显示,不落回通用文案', () => {
it('调用通道失联使用专用 IPC 文案,不冒充业务原因', () => {
expect(homeCreationFailureMessage(new Error('Failed to fetch'))).toBe(
HOME_CREATION_IPC_FAILURE,
`${HOME_CREATION_IPC_FAILURE}(Failed to fetch)`,
);
expect(
homeCreationFailureMessage(
@@ -37,12 +37,14 @@ it('调用通道失联使用专用 IPC 文案,不冒充业务原因', () => {
),
{ projectCreated: true },
),
).toBe(HOME_CREATION_AFTER_PROJECT_IPC_FAILURE);
).toBe(
`${HOME_CREATION_AFTER_PROJECT_IPC_FAILURE}(IPC custom protocol failed, Tauri will now use the postMessage interface instead TypeError: Failed to fetch)`,
);
});
it('拿不到任何机器码时使用专用兜底,并按是否已建好工作区分文案', () => {
expect(homeCreationFailureMessage(new Error('自动创建测试结束'))).toBe(
HOME_CREATION_UNCLASSIFIED_FAILURE,
`${HOME_CREATION_UNCLASSIFIED_FAILURE}(自动创建测试结束)`,
);
expect(homeCreationFailureMessage(undefined)).toBe(
HOME_CREATION_UNCLASSIFIED_FAILURE,
@@ -51,7 +53,9 @@ it('拿不到任何机器码时使用专用兜底,并按是否已建好工作
homeCreationFailureMessage(new Error('design runtime unavailable'), {
projectCreated: true,
}),
).toBe(HOME_CREATION_AFTER_PROJECT_FAILURE);
).toBe(
`${HOME_CREATION_AFTER_PROJECT_FAILURE}(design runtime unavailable)`,
);
});
it('宿主原始文本只进诊断,不进用户文案', () => {
@@ -60,7 +64,9 @@ it('宿主原始文本只进诊断,不进用户文案', () => {
{ projectCreated: false },
);
expect(failure).toBeInstanceOf(HomeCreationFailure);
expect(failure.userMessage).toBe(HOME_CREATION_UNCLASSIFIED_FAILURE);
expect(failure.userMessage).toBe(
`${HOME_CREATION_UNCLASSIFIED_FAILURE}(Provider 返回 500:<url>)`,
);
expect(failure.diagnostic).toBe(
'Provider 返回 500:https://provider.example/private',
);