Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions apps/desktop/renderer-architecture.json
Original file line number Diff line number Diff line change
Expand Up @@ -1647,7 +1647,9 @@
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {}
"dependencyPaths": {
"@maka/core/ui-locale": 1
}
},
"src/renderer/locales/settings-memory-copy.ts": {
"bridgePaths": {},
Expand All @@ -1656,7 +1658,9 @@
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {}
"dependencyPaths": {
"@maka/core/ui-locale": 1
}
},
"src/renderer/locales/settings-navigation-copy.ts": {
"bridgePaths": {},
Expand Down
8 changes: 4 additions & 4 deletions apps/desktop/src/main/__tests__/computer-use-host.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,27 @@ describe('Computer Use host health', () => {
it('does not report a binary-only executor as healthy before first use', () => {
assert.deepEqual(computerUseServiceHealth('maka-cu', snapshot('idle')), {
state: 'not_run',
reason: 'maka-cu 已可用,将在首次调用时启动。',
reason: 'cu_executor_lazy_start',
});
});

it('reports ready, recovery, and unavailable states', () => {
assert.equal(computerUseServiceHealth('maka-cu', snapshot('ready')).state, 'healthy');
assert.equal(
computerUseServiceHealth('maka-cu', snapshot('backing_off')).reason,
'maka-cu executor 正在启动或恢复。',
'cu_executor_recovering',
);
assert.equal(
computerUseServiceHealth('maka-cu', snapshot('starting')).state,
'degraded',
);
assert.deepEqual(computerUseServiceHealth('maka-cu', snapshot('unavailable')), {
state: 'not_available',
reason: 'maka-cu executor 启动失败或已退出。',
reason: 'cu_executor_start_failed',
});
assert.deepEqual(computerUseServiceHealth('maka-cu', snapshot('disposed')), {
state: 'not_available',
reason: 'maka-cu executor 已停止。',
reason: 'cu_executor_stopped',
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('importGitHubCopilotLocalCredential', () => {
assert.equal(imported.result.ok, false);
if (!imported.result.ok) {
assert.equal(imported.result.reason, 'token_exchange_failed');
assert.match(imported.result.message, /不支持 classic PAT/);
assert.equal(imported.result.code, 'copilot_classic_pat_unsupported');
assert.equal(imported.result.message.includes('ghp_classic_pat'), false);
}
assert.equal(imported.secret, undefined);
Expand All @@ -83,7 +83,7 @@ describe('importGitHubCopilotLocalCredential', () => {
});

assert.equal(imported.result.ok, false);
if (!imported.result.ok) assert.match(imported.result.message, /凭据类型不受支持/);
if (!imported.result.ok) assert.equal(imported.result.code, 'copilot_credential_type_unsupported');
assert.equal(imported.secret, undefined);
});

Expand All @@ -95,7 +95,7 @@ describe('importGitHubCopilotLocalCredential', () => {
});

assert.equal(imported.result.ok, false);
if (!imported.result.ok) assert.match(imported.result.message, /未找到可导入/);
if (!imported.result.ok) assert.equal(imported.result.code, 'copilot_local_credential_missing');
assert.equal(imported.secret, undefined);
});
});
40 changes: 23 additions & 17 deletions apps/desktop/src/main/__tests__/health-center-copy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import assert from 'node:assert/strict';
import { test } from 'node:test';
import { CAPABILITY_REASON_CODES } from '@maka/core/capabilities';
import { UI_LOCALES, type UiCatalog } from '@maka/core/ui-locale';
import { connectionLastTestMessageDisplay } from '../../renderer/features/connection-settings/index.js';
import { getHealthCenterCopy } from '../../renderer/locales/settings-health-copy.js';

Expand Down Expand Up @@ -96,23 +98,27 @@ test('renders runtime probe details from structured params, not string parsing',
);
});

test('keeps zh capability reasons and hides wrong-locale ones', () => {
const zhReason = { kind: 'capability_reason', reason: '未配置平台凭据' } as const;
assert.equal(getHealthCenterCopy('zh-CN').signalDetail(signal({ detail: zhReason })), '未配置平台凭据');
assert.equal(
getHealthCenterCopy('en').signalDetail(signal({ detail: zhReason })),
'See the corresponding settings page for details.',
);

const enReason = { kind: 'capability_reason', reason: 'Slack requires a Bot Token.' } as const;
assert.equal(
getHealthCenterCopy('zh-CN').signalDetail(signal({ detail: enReason })),
'状态详情请见对应设置页。',
);
assert.equal(
getHealthCenterCopy('en').signalDetail(signal({ detail: enReason })),
'See the corresponding settings page for details.',
);
test('renders capability codes in all locales without inspecting prose', () => {
const expected = {
'zh-CN': ['maka-cu executor 正在启动或恢复。', '等待填写平台凭据。', '状态详情请见对应设置页。'],
'zh-TW': ['maka-cu executor 正在啟動或恢復。', '等待填寫平台憑據。', '狀態詳細資料請參閱對應的設定頁。'],
en: ['The maka-cu executor is starting or recovering.', 'Waiting for platform credentials.', 'See the corresponding settings page for details.'],
} satisfies UiCatalog<readonly [string, string, string]>;
for (const locale of UI_LOCALES) {
const copy = getHealthCenterCopy(locale);
const [recovering, credentials, fallback] = expected[locale];
const render = (reason: string) => copy.signalDetail(signal({ detail: { kind: 'capability_reason', reason } }));
assert.equal(render('cu_executor_recovering'), recovering);
assert.equal(render('missing platform credentials'), credentials);
for (const code of CAPABILITY_REASON_CODES) {
assert.equal(typeof render(code), 'string');
assert.notEqual(render(code), fallback, `${locale}: ${code} must have copy`);
assert.notEqual(render(code), code);
}
for (const reason of ['future_code', '未配置平台凭据', 'Slack requires a Bot Token.', 'toString', '__proto__']) {
assert.equal(render(reason), fallback);
}
}
});

test('maps connection test error classes without exposing machine tokens', () => {
Expand Down
60 changes: 60 additions & 0 deletions apps/desktop/src/main/__tests__/oauth-result-copy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import assert from "node:assert/strict";
import test from "node:test";
// Lives under main/__tests__ on purpose: desktop main tests run from dist via
// `node --test "dist/main/**/*.test.js"`, and settings-provider-copy is a pure
// copy module (no react), so it is safe to exercise from node. Same precedent
// as permission-center-copy.test.ts.
import {
connectionTestFailureMessage,
subscriptionResultMessage,
} from "../../renderer/features/connection-settings/index.js";

test("renders a coded Copilot import failure per locale, ignoring its machine message", () => {
const result = { code: "copilot_subscription_unavailable", message: "copilot_subscription_unavailable" };
assert.equal(subscriptionResultMessage(result, "fallback", "zh-CN"), "当前 GitHub 账号没有可用的 Copilot 订阅权限。");
assert.equal(subscriptionResultMessage(result, "fallback", "en"), "This GitHub account has no usable Copilot subscription.");
});

test("renders the typed experimental_disabled reason per locale", () => {
const result = { reason: "experimental_disabled", message: "enrollment is disabled for this provider" };
assert.equal(subscriptionResultMessage(result, "fallback", "zh-CN"), "本机未启用该账号登录方式;可改用导入兼容凭据,或由管理员启用后重试。");
assert.equal(subscriptionResultMessage(result, "fallback", "en"), "This sign-in is not enabled on this install. Import a compatible credential instead, or ask an operator to enable it.");
});

test("falls back to catalog copy for an unknown code instead of the raw message", () => {
const result = { code: "not_a_known_code", message: "内部错误" };
assert.equal(subscriptionResultMessage(result, "fallback", "en"), "fallback");
assert.equal(subscriptionResultMessage(result, "fallback", "zh-CN"), "fallback");
});

test("renders provider rate limits consistently from the stable status code", () => {
const result = { ok: false, statusCode: 429, errorClass: "provider_unavailable" } as const;
const troubleshooting = { auth: "auth", recheck: "recheck" };
assert.equal(
connectionTestFailureMessage(result, troubleshooting, "zh-CN"),
"当前账号或模型服务触发速率限制,请稍后重试。",
);
assert.equal(
connectionTestFailureMessage(result, troubleshooting, "en"),
"This account or model service is rate-limited. Try again later.",
);
});
26 changes: 26 additions & 0 deletions apps/desktop/src/main/__tests__/permission-center-copy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,29 @@ test('presents a granted OS permission as a verified success', () => {
assert.equal(getPermissionCenterCopy('zh-CN').osStates.granted.tone, 'success');
assert.equal(getPermissionCenterCopy('en').osStates.granted.tone, 'success');
});

test('renders capability reason codes per locale', () => {
const zh = getPermissionCenterCopy('zh-CN');
const en = getPermissionCenterCopy('en');
assert.equal(zh.reasons['missing platform credentials'], '未配置平台凭据');
assert.equal(en.reasons['missing platform credentials'], 'Platform credentials are not configured');
assert.equal(zh.reasons.cu_executor_recovering, 'maka-cu executor 正在启动或恢复。');
assert.equal(en.reasons.cu_executor_recovering, 'The maka-cu executor is starting or recovering.');
});

test('composes the computer-use backend status from snapshot facts per locale', () => {
const zh = getPermissionCenterCopy('zh-CN');
const en = getPermissionCenterCopy('en');
assert.equal(
zh.cuBackendStatus(['辅助功能', '屏幕录制'], 'healthy'),
'maka-cu artifact 已通过本地完整性检查。等待辅助功能、屏幕录制权限。操作与截图 service 已就绪;按目标与动作类别授权后可操作本机应用。',
);
assert.equal(
zh.cuBackendStatus([], 'not_run'),
'maka-cu artifact 已通过本地完整性检查。service 将在首次调用时启动;按目标与动作类别授权后可操作本机应用。',
);
assert.equal(
en.cuBackendStatus(['Accessibility'], 'degraded'),
'The maka-cu artifact passed the local integrity check. Waiting for Accessibility permission. The maka-cu service is starting or recovering.',
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function attachmentReadHandler(
): Handler {
const handlers = new Map<string, Handler>();
registerRuntimeHostArtifactsIpc({
uiLocale: () => 'zh-CN' as const,
ipcMain: {
handle: (channel, handler) => handlers.set(channel, handler as Handler),
},
Expand Down Expand Up @@ -121,6 +122,7 @@ test("Runtime Host Artifact IPC preserves previews and streams complete exports"

try {
registerRuntimeHostArtifactsIpc({
uiLocale: () => 'zh-CN' as const,
ipcMain: {
handle: (channel, handler) => handlers.set(channel, handler as Handler),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ test('does not project or open remote Runtime Host file paths', async () => {
assert.deepEqual(projected.backups.map(({ path }) => path), ['']);
assert.deepEqual(opened, {
ok: false,
code: 'remote_host_owned',
message: 'Memory files are owned by the remote Runtime Host',
});
});
Expand Down
Loading