feat: implement macOS notarization and ad-hoc signing in afterSign script
feat: add run-server script to manage server execution and compatibility checks feat: create main application logic for desktop with window management, server handling, and auto-updater test: add unit tests for desktop runtime helpers feat: implement desktop server environment configuration and health check test: add tests for server configuration and desktop routes feat: add native module guard for better-sqlite3 compatibility test: add tests for native module guard functionality test: add comprehensive tests for account verification feedback handling feat: implement account verification feedback helpers chore: add TypeScript configuration for desktop builds
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
buildAddAccountPrereqHint,
|
||||
buildVerifyFailureHint,
|
||||
normalizeVerifyFailureMessage,
|
||||
} from './accountVerifyFeedback.js';
|
||||
|
||||
describe('account verify feedback', () => {
|
||||
it('treats fetch failures as connectivity issues instead of token mistakes', () => {
|
||||
expect(normalizeVerifyFailureMessage('Failed to fetch')).not.toBe('Failed to fetch');
|
||||
expect(buildVerifyFailureHint({ success: false, message: 'Failed to fetch' })).not.toBeNull();
|
||||
expect(buildAddAccountPrereqHint({ success: false, message: 'Failed to fetch' })).toMatch(/metapi|站点|代理/i);
|
||||
});
|
||||
|
||||
it('treats timeout failures as reachability issues instead of token mistakes', () => {
|
||||
const timeoutMessage = 'Token verification timed out (10s)';
|
||||
expect(normalizeVerifyFailureMessage(timeoutMessage)).toBe(timeoutMessage);
|
||||
expect(buildVerifyFailureHint({ success: false, message: timeoutMessage })).toMatch(/Token|站点|代理|超时/i);
|
||||
expect(buildAddAccountPrereqHint({ success: false, message: timeoutMessage })).toMatch(/站点|代理|超时/i);
|
||||
});
|
||||
|
||||
it('keeps token guidance for actual credential failures', () => {
|
||||
const invalidHint = buildVerifyFailureHint({ success: false, message: 'Token invalid' });
|
||||
expect(invalidHint).toMatch(/Token/i);
|
||||
expect(buildAddAccountPrereqHint({ success: false, message: 'Token invalid' })).toMatch(/Token/i);
|
||||
});
|
||||
|
||||
it('normalizes invalid user-id mismatch messages for display', () => {
|
||||
expect(normalizeVerifyFailureMessage('The provided user ID does not match this token. Please check your site user ID.'))
|
||||
.toMatch(/ID/i);
|
||||
expect(normalizeVerifyFailureMessage('The provided user ID does not match this token. Please check your site user ID.'))
|
||||
.not.toContain('does not match this token');
|
||||
});
|
||||
|
||||
it('prioritizes user-id guidance when the site requires it', () => {
|
||||
expect(buildVerifyFailureHint({ success: false, needsUserId: true, message: 'missing New-Api-User' })).toBeNull();
|
||||
expect(buildAddAccountPrereqHint({ success: false, needsUserId: true, message: 'missing New-Api-User' })).toMatch(/ID/i);
|
||||
});
|
||||
|
||||
it('treats invalid user-id as a mismatch instead of a missing-value hint', () => {
|
||||
const invalidUserIdHint = buildVerifyFailureHint({ success: false, invalidUserId: true, message: 'user id mismatch' });
|
||||
const genericTokenHint = buildVerifyFailureHint({ success: false, message: 'Token invalid' });
|
||||
const invalidUserIdPrereq = buildAddAccountPrereqHint({ success: false, invalidUserId: true, message: 'user id mismatch' });
|
||||
const genericPrereq = buildAddAccountPrereqHint({ success: false, message: 'Token invalid' });
|
||||
|
||||
expect(invalidUserIdHint).toMatch(/ID/i);
|
||||
expect(invalidUserIdHint).not.toBe(genericTokenHint);
|
||||
expect(invalidUserIdPrereq).toMatch(/ID/i);
|
||||
expect(invalidUserIdPrereq).not.toBe(genericPrereq);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
type VerifyResultLike = {
|
||||
success?: boolean;
|
||||
needsUserId?: boolean;
|
||||
invalidUserId?: boolean;
|
||||
message?: string | null;
|
||||
} | null | undefined;
|
||||
|
||||
function normalizeMessageText(message: unknown): string {
|
||||
return typeof message === 'string' ? message.trim() : '';
|
||||
}
|
||||
|
||||
export function isNetworkFailureMessage(message: unknown): boolean {
|
||||
const lowered = normalizeMessageText(message).toLowerCase();
|
||||
return lowered.includes('failed to fetch')
|
||||
|| lowered.includes('fetch failed')
|
||||
|| lowered.includes('networkerror')
|
||||
|| lowered.includes('load failed');
|
||||
}
|
||||
|
||||
export function isTimeoutFailureMessage(message: unknown): boolean {
|
||||
const lowered = normalizeMessageText(message).toLowerCase();
|
||||
return lowered.includes('timed out')
|
||||
|| lowered.includes('timeout')
|
||||
|| lowered.includes('请求超时');
|
||||
}
|
||||
|
||||
export function normalizeVerifyFailureMessage(message: unknown): string {
|
||||
const text = normalizeMessageText(message);
|
||||
if (!text) return '验证失败';
|
||||
const lowered = text.toLowerCase();
|
||||
if (isNetworkFailureMessage(text)) {
|
||||
return '无法连接到 metapi 服务端,请检查服务状态或网络连接';
|
||||
}
|
||||
if (lowered.includes('user id mismatch') || lowered.includes('does not match this token')) {
|
||||
return '填写的用户 ID 与当前 Token / Cookie 不匹配';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function buildVerifyFailureHint(result: VerifyResultLike): string | null {
|
||||
if (!result || result.success || result.needsUserId) return null;
|
||||
if (result.invalidUserId) {
|
||||
return '这不是 Token 错误判断。请检查填写的用户 ID 是否与当前 Token / Cookie 属于同一账号。';
|
||||
}
|
||||
if (isNetworkFailureMessage(result.message)) {
|
||||
return '这不是 Token 错误判断。请检查 metapi 服务是否在线,以及目标站点或代理是否可达。';
|
||||
}
|
||||
if (isTimeoutFailureMessage(result.message)) {
|
||||
return '这不是 Token 错误判断。目标站点响应超时,请稍后重试或检查代理/网络。';
|
||||
}
|
||||
return '请检查 Token 是否正确';
|
||||
}
|
||||
|
||||
export function buildAddAccountPrereqHint(result: VerifyResultLike): string {
|
||||
if (!result) {
|
||||
return '请先点击“验证 Token”,验证成功后才能添加账号。';
|
||||
}
|
||||
if (result.success) return '';
|
||||
if (result.needsUserId) {
|
||||
return '请先补充用户 ID 并重新验证,验证成功后才能添加账号。';
|
||||
}
|
||||
if (result.invalidUserId) {
|
||||
return '请先修正用户 ID 并重新验证,验证成功后才能添加账号。';
|
||||
}
|
||||
if (isNetworkFailureMessage(result.message)) {
|
||||
return '验证请求未成功完成,请先检查 metapi 服务、站点网络或代理配置。';
|
||||
}
|
||||
if (isTimeoutFailureMessage(result.message)) {
|
||||
return '验证请求超时,请先检查站点或代理连通性后再添加账号。';
|
||||
}
|
||||
return '请先点击“验证 Token”,验证成功后才能添加账号。';
|
||||
}
|
||||
Reference in New Issue
Block a user