补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。 Co-authored-by: Cursor <cursoragent@cursor.com>
605 行
20 KiB
TypeScript
605 行
20 KiB
TypeScript
/**
|
||
* OmniCard AI (CRMmp) - mpuniapp 统一登录骨架测试套件 (TDD Red -> Green)
|
||
*
|
||
* 严格按照 AGENTS.md 3.3、4.3、5.1 规范与 PRD pages/common/login 设计编写
|
||
*/
|
||
|
||
type UniToastOption = {
|
||
title: string;
|
||
icon?: string;
|
||
};
|
||
|
||
type UniRequestSuccessRes = {
|
||
statusCode: number;
|
||
data: unknown;
|
||
header: Record<string, string>;
|
||
};
|
||
|
||
type UniRequestOption = {
|
||
url: string;
|
||
method?: string;
|
||
data?: Record<string, unknown>;
|
||
success?: (res: UniRequestSuccessRes) => void;
|
||
fail?: (err: { errMsg: string }) => void;
|
||
complete?: () => void;
|
||
};
|
||
|
||
type LoginState = {
|
||
tab: 'password' | 'phone' | 'email';
|
||
username: string;
|
||
password: string;
|
||
countryCode: string;
|
||
phone: string;
|
||
smsCode: string;
|
||
email: string;
|
||
submitting: boolean;
|
||
errorMessage: string;
|
||
countdown: number;
|
||
};
|
||
|
||
type UseLoginModule = {
|
||
createLoginState: () => LoginState;
|
||
completeLogin: (token: string, tenantId?: string) => boolean;
|
||
submitPasswordLogin: (state: LoginState) => Promise<boolean>;
|
||
submitPhoneLogin: (state: LoginState) => Promise<boolean>;
|
||
sendMagicLink: (state: LoginState) => Promise<boolean>;
|
||
sendSmsCode: (state: LoginState) => Promise<boolean>;
|
||
tapSocialLogin: (provider: 'google' | 'apple') => Promise<void>;
|
||
resolveLoginText: (key: string) => string;
|
||
tickCountdown: (state: LoginState) => void;
|
||
fillTestAccount: (state: LoginState) => void;
|
||
};
|
||
|
||
type MockPayload = {
|
||
statusCode?: number;
|
||
data?: unknown;
|
||
failError?: { errMsg: string };
|
||
};
|
||
|
||
describe('OmniCard AI 用户端统一登录业务逻辑测试 (useLogin.uts)', () => {
|
||
let storageMap: Map<string, string>;
|
||
let toastCalls: UniToastOption[];
|
||
let lastRequestOptions: UniRequestOption | null;
|
||
let requestCallCount: number;
|
||
let navigateBackCount: number;
|
||
let switchTabCount: number;
|
||
let clipboardCalls: Array<{ data: string }>;
|
||
let openUrlCalls: string[];
|
||
let mockByUrl: Map<string, MockPayload>;
|
||
let defaultMock: MockPayload;
|
||
|
||
beforeEach(() => {
|
||
storageMap = new Map();
|
||
toastCalls = [];
|
||
lastRequestOptions = null;
|
||
requestCallCount = 0;
|
||
navigateBackCount = 0;
|
||
switchTabCount = 0;
|
||
clipboardCalls = [];
|
||
openUrlCalls = [];
|
||
mockByUrl = new Map();
|
||
defaultMock = {
|
||
statusCode: 200,
|
||
data: { code: 1000, message: 'success', data: {} },
|
||
};
|
||
jest.resetModules();
|
||
|
||
(global as { uni?: Record<string, unknown> }).uni = {
|
||
getStorageSync: (key: string) => storageMap.get(key) || '',
|
||
setStorageSync: (key: string, val: string) => storageMap.set(key, val),
|
||
removeStorageSync: (key: string) => storageMap.delete(key),
|
||
showToast: (options: UniToastOption) => {
|
||
toastCalls.push(options);
|
||
},
|
||
reLaunch: jest.fn(),
|
||
switchTab: (_options: { url: string }) => {
|
||
switchTabCount += 1;
|
||
},
|
||
navigateBack: () => {
|
||
navigateBackCount += 1;
|
||
},
|
||
setClipboardData: (options: { data: string; success?: () => void }) => {
|
||
clipboardCalls.push({ data: options.data });
|
||
options.success?.();
|
||
},
|
||
getLocale: () => 'zh-CN',
|
||
request: (options: UniRequestOption) => {
|
||
requestCallCount += 1;
|
||
lastRequestOptions = options;
|
||
const matched = Array.from(mockByUrl.entries()).find(([path]) =>
|
||
(options.url || '').includes(path)
|
||
);
|
||
const payload = matched ? matched[1] : defaultMock;
|
||
setTimeout(() => {
|
||
if (payload.failError) {
|
||
options.fail?.(payload.failError);
|
||
} else {
|
||
options.success?.({
|
||
statusCode: payload.statusCode ?? 200,
|
||
data: payload.data,
|
||
header: {},
|
||
});
|
||
}
|
||
options.complete?.();
|
||
}, 0);
|
||
return {
|
||
abort: jest.fn(),
|
||
};
|
||
},
|
||
};
|
||
|
||
(global as { window?: { open?: (url: string) => void } }).window = {
|
||
open: (url: string) => {
|
||
openUrlCalls.push(url);
|
||
},
|
||
};
|
||
});
|
||
|
||
afterEach(() => {
|
||
delete (global as { uni?: Record<string, unknown> }).uni;
|
||
delete (global as { window?: unknown }).window;
|
||
});
|
||
|
||
function loadUseLogin(): UseLoginModule {
|
||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||
return require('../../../mpuniapp/pages/common/useLogin.uts') as UseLoginModule;
|
||
}
|
||
|
||
function mockEndpoint(path: string, data: unknown, statusCode = 200): void {
|
||
mockByUrl.set(path, {
|
||
statusCode,
|
||
data: { code: 1000, message: 'success', data },
|
||
});
|
||
}
|
||
|
||
describe('1. completeLogin 写入本地凭证', () => {
|
||
it('1.1 completeLogin 会 setStorage token 并跳转名片页', () => {
|
||
const { completeLogin } = loadUseLogin();
|
||
|
||
const ok = completeLogin('mock_jwt_login_t09');
|
||
|
||
expect(ok).toBe(true);
|
||
expect(storageMap.get('token')).toBe('mock_jwt_login_t09');
|
||
expect(switchTabCount).toBe(1);
|
||
});
|
||
|
||
it('1.2 传入 tenantId 时同步写入 tenant_id', () => {
|
||
const { completeLogin } = loadUseLogin();
|
||
|
||
completeLogin('mock_jwt_login_t09', 'tenant_omni_88');
|
||
|
||
expect(storageMap.get('token')).toBe('mock_jwt_login_t09');
|
||
expect(storageMap.get('tenant_id')).toBe('tenant_omni_88');
|
||
expect(switchTabCount).toBe(1);
|
||
});
|
||
|
||
it('1.3 未传 tenantId 时不写入 tenant_id', () => {
|
||
const { completeLogin } = loadUseLogin();
|
||
|
||
completeLogin('mock_jwt_only_token');
|
||
|
||
expect(storageMap.get('token')).toBe('mock_jwt_only_token');
|
||
expect(storageMap.has('tenant_id')).toBe(false);
|
||
expect(switchTabCount).toBe(1);
|
||
});
|
||
});
|
||
|
||
describe('2. 空手机号 / 空邮箱不提交', () => {
|
||
it('2.1 空手机号不提交验证码登录', async () => {
|
||
const { createLoginState, submitPhoneLogin } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
state.smsCode = '123456';
|
||
|
||
const ok = await submitPhoneLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(requestCallCount).toBe(0);
|
||
expect(lastRequestOptions).toBeNull();
|
||
expect(toastCalls.length).toBeGreaterThan(0);
|
||
expect(toastCalls[0].title).toContain('手机号');
|
||
});
|
||
|
||
it('2.2 空邮箱不提交 Magic Link', async () => {
|
||
const { createLoginState, sendMagicLink } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
state.tab = 'email';
|
||
|
||
const ok = await sendMagicLink(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(requestCallCount).toBe(0);
|
||
expect(lastRequestOptions).toBeNull();
|
||
expect(toastCalls.length).toBeGreaterThan(0);
|
||
expect(toastCalls[0].title).toContain('邮箱');
|
||
});
|
||
});
|
||
|
||
describe('3. 外部登录:未配置不写 token / sent 不写 / ok 才写', () => {
|
||
it('3.1 smsSend not_configured:toast 即将开放且不写 token', async () => {
|
||
mockEndpoint('/app/user/external/smsSend', { status: 'not_configured' });
|
||
const { createLoginState, sendSmsCode } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
|
||
const ok = await sendSmsCode(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(lastRequestOptions?.url).toContain('/app/user/external/smsSend');
|
||
expect(lastRequestOptions?.data).toEqual({ phone: '13800138000' });
|
||
expect(toastCalls[toastCalls.length - 1].title).toContain('即将开放');
|
||
expect(state.countdown).toBe(0);
|
||
});
|
||
|
||
it('3.2 smsSend sent:提示已发送,不写 token,启动倒计时', async () => {
|
||
mockEndpoint('/app/user/external/smsSend', { status: 'sent' });
|
||
const { createLoginState, sendSmsCode, tickCountdown } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
|
||
const ok = await sendSmsCode(state);
|
||
|
||
expect(ok).toBe(true);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(state.countdown).toBe(60);
|
||
expect(toastCalls[toastCalls.length - 1].title).toMatch(/已发送|sent/i);
|
||
tickCountdown(state);
|
||
expect(state.countdown).toBe(59);
|
||
const again = await sendSmsCode(state);
|
||
expect(again).toBe(false);
|
||
expect(state.countdown).toBe(59);
|
||
});
|
||
|
||
it('3.3 smsLogin not_configured:不写 token', async () => {
|
||
mockEndpoint('/app/user/external/smsLogin', { status: 'not_configured' });
|
||
const { createLoginState, submitPhoneLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
state.smsCode = '123456';
|
||
|
||
const ok = await submitPhoneLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(lastRequestOptions?.url).toContain('/app/user/external/smsLogin');
|
||
expect(lastRequestOptions?.data).toEqual({ phone: '13800138000', code: '123456' });
|
||
expect(toastCalls[toastCalls.length - 1].title).toContain('即将开放');
|
||
});
|
||
|
||
it('3.4 smsLogin ok + token:写入 token 并跳转', async () => {
|
||
mockEndpoint('/app/user/external/smsLogin', {
|
||
status: 'ok',
|
||
token: 'mock_sms_jwt_token',
|
||
});
|
||
const { createLoginState, submitPhoneLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
state.smsCode = '654321';
|
||
|
||
const ok = await submitPhoneLogin(state);
|
||
|
||
expect(ok).toBe(true);
|
||
expect(storageMap.get('token')).toBe('mock_sms_jwt_token');
|
||
expect(switchTabCount).toBe(1);
|
||
});
|
||
|
||
it('3.5 smsLogin 请求失败:不写 token', async () => {
|
||
mockByUrl.set('/app/user/external/smsLogin', {
|
||
statusCode: 200,
|
||
data: { code: 1001, message: '验证码错误' },
|
||
});
|
||
const { createLoginState, submitPhoneLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
state.smsCode = '000000';
|
||
|
||
const ok = await submitPhoneLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
});
|
||
|
||
it('3.6 magicLink not_configured:不写 token', async () => {
|
||
mockEndpoint('/app/user/external/magicLink', { status: 'not_configured' });
|
||
const { createLoginState, sendMagicLink } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.email = 'demo@omnicard.ai';
|
||
|
||
const ok = await sendMagicLink(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(lastRequestOptions?.url).toContain('/app/user/external/magicLink');
|
||
expect(lastRequestOptions?.data).toEqual({ email: 'demo@omnicard.ai' });
|
||
expect(toastCalls[toastCalls.length - 1].title).toContain('即将开放');
|
||
});
|
||
|
||
it('3.7 magicLink sent:提示已发送,不写 token', async () => {
|
||
mockEndpoint('/app/user/external/magicLink', { status: 'sent' });
|
||
const { createLoginState, sendMagicLink } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.email = 'demo@omnicard.ai';
|
||
|
||
const ok = await sendMagicLink(state);
|
||
|
||
expect(ok).toBe(true);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(toastCalls[toastCalls.length - 1].title).toMatch(/已发送|sent/i);
|
||
});
|
||
|
||
it('3.8 magicLink ok + token:写入 token', async () => {
|
||
mockEndpoint('/app/user/external/magicLink', {
|
||
status: 'ok',
|
||
token: 'mock_magic_jwt_token',
|
||
});
|
||
const { createLoginState, sendMagicLink } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.email = 'demo@omnicard.ai';
|
||
|
||
const ok = await sendMagicLink(state);
|
||
|
||
expect(ok).toBe(true);
|
||
expect(storageMap.get('token')).toBe('mock_magic_jwt_token');
|
||
expect(switchTabCount).toBe(1);
|
||
});
|
||
|
||
it('3.9 Google not_configured 且无 url:toast 即将开放,不写 token,不打开假地址', async () => {
|
||
mockEndpoint('/app/user/external/googleStart', { status: 'not_configured' });
|
||
const { tapSocialLogin } = loadUseLogin();
|
||
|
||
await tapSocialLogin('google');
|
||
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(lastRequestOptions?.url).toContain('/app/user/external/googleStart');
|
||
expect(toastCalls[toastCalls.length - 1].title).toContain('即将开放');
|
||
expect(openUrlCalls.length).toBe(0);
|
||
expect(clipboardCalls.length).toBe(0);
|
||
});
|
||
|
||
it('3.10 Apple 返回 url:可复制或打开,不写 token', async () => {
|
||
mockEndpoint('/app/user/external/appleStart', {
|
||
status: 'ok',
|
||
url: 'https://appleid.apple.com/auth/authorize?client_id=omni',
|
||
});
|
||
const { tapSocialLogin } = loadUseLogin();
|
||
|
||
await tapSocialLogin('apple');
|
||
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(lastRequestOptions?.url).toContain('/app/user/external/appleStart');
|
||
const openedOrCopied =
|
||
openUrlCalls.includes('https://appleid.apple.com/auth/authorize?client_id=omni') ||
|
||
clipboardCalls.some(
|
||
(c) => c.data === 'https://appleid.apple.com/auth/authorize?client_id=omni'
|
||
);
|
||
expect(openedOrCopied).toBe(true);
|
||
});
|
||
|
||
it('3.11 社交登录请求失败:不写 token', async () => {
|
||
mockByUrl.set('/app/user/external/googleStart', {
|
||
failError: { errMsg: 'network error' },
|
||
});
|
||
const { tapSocialLogin } = loadUseLogin();
|
||
|
||
await tapSocialLogin('google');
|
||
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(openUrlCalls.length).toBe(0);
|
||
});
|
||
|
||
it('3.12 smsLogin status=ok 但无 token:不写凭证,不跳转', async () => {
|
||
mockEndpoint('/app/user/external/smsLogin', { status: 'ok' });
|
||
const { createLoginState, submitPhoneLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
state.smsCode = '123456';
|
||
|
||
const ok = await submitPhoneLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
});
|
||
});
|
||
|
||
describe('4. 极简品牌感文案与国际化解析', () => {
|
||
it('4.1 正确解析品牌感文案,杜绝空字符串与硬编码', () => {
|
||
const { resolveLoginText } = loadUseLogin();
|
||
|
||
expect(resolveLoginText('brandTag').length).toBeGreaterThan(0);
|
||
expect(resolveLoginText('subtitle').length).toBeGreaterThan(0);
|
||
expect(resolveLoginText('orContinueWith').length).toBeGreaterThan(0);
|
||
expect(resolveLoginText('termsNotice').length).toBeGreaterThan(0);
|
||
expect(resolveLoginText('termsOfService').length).toBeGreaterThan(0);
|
||
expect(resolveLoginText('privacyPolicy').length).toBeGreaterThan(0);
|
||
});
|
||
});
|
||
|
||
describe('5. 验证码倒计时机制', () => {
|
||
it('5.1 手机号合法且 smsSend sent 时触发 60s 倒计时', async () => {
|
||
mockEndpoint('/app/user/external/smsSend', { status: 'sent' });
|
||
const { createLoginState, sendSmsCode, tickCountdown } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
state.phone = '13800138000';
|
||
|
||
await sendSmsCode(state);
|
||
expect(state.countdown).toBe(60);
|
||
|
||
tickCountdown(state);
|
||
expect(state.countdown).toBe(59);
|
||
|
||
const again = await sendSmsCode(state);
|
||
expect(again).toBe(false);
|
||
expect(state.countdown).toBe(59);
|
||
});
|
||
});
|
||
|
||
describe('6. 账号密码真实登录与前后端对齐', () => {
|
||
it('6.1 空账号或空密码不提交', async () => {
|
||
const { createLoginState, submitPasswordLogin } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
state.username = '';
|
||
state.password = '';
|
||
|
||
const ok = await submitPasswordLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(requestCallCount).toBe(0);
|
||
expect(toastCalls.length).toBeGreaterThan(0);
|
||
expect(toastCalls[0].title).toContain('账号');
|
||
|
||
state.username = 'admin';
|
||
state.password = '';
|
||
const ok2 = await submitPasswordLogin(state);
|
||
expect(ok2).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(toastCalls[toastCalls.length - 1].title).toContain('密码');
|
||
});
|
||
|
||
it('6.2 账号密码登录成功:对齐 /admin/base/open/login 接口契约,写入 token 并跳转', async () => {
|
||
const { createLoginState, submitPasswordLogin } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
state.username = 'admin';
|
||
state.password = '123456';
|
||
|
||
mockEndpoint('/admin/base/open/login', {
|
||
token: 'mock_admin_jwt_token_2026',
|
||
expire: 7200,
|
||
refreshToken: 'mock_refresh_token',
|
||
});
|
||
|
||
const ok = await submitPasswordLogin(state);
|
||
|
||
expect(ok).toBe(true);
|
||
expect(storageMap.get('token')).toBe('mock_admin_jwt_token_2026');
|
||
expect(switchTabCount).toBe(1);
|
||
expect(lastRequestOptions?.url).toContain('/admin/base/open/login');
|
||
expect(lastRequestOptions?.data).toEqual({
|
||
username: 'admin',
|
||
password: '123456',
|
||
});
|
||
});
|
||
|
||
it('6.3 账号密码登录失败:后端返回 1001 时正确提示错误并置错误信息', async () => {
|
||
const { createLoginState, submitPasswordLogin } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
state.username = 'admin';
|
||
state.password = 'wrong_password';
|
||
|
||
mockByUrl.set('/admin/base/open/login', {
|
||
statusCode: 200,
|
||
data: {
|
||
code: 1001,
|
||
message: '账户或密码不正确~',
|
||
},
|
||
});
|
||
|
||
const ok = await submitPasswordLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
expect(state.errorMessage).toBe('账户或密码不正确~');
|
||
expect(toastCalls[toastCalls.length - 1].title).toBe('账户或密码不正确~');
|
||
});
|
||
|
||
it('6.4 一键填入测试账号便于快速验证', () => {
|
||
const { createLoginState, fillTestAccount } = loadUseLogin();
|
||
|
||
const state = createLoginState();
|
||
expect(state.username).toBe('');
|
||
expect(state.password).toBe('');
|
||
|
||
fillTestAccount(state);
|
||
|
||
expect(state.username).toBe('admin');
|
||
expect(state.password).toBe('123456');
|
||
});
|
||
|
||
it('6.5 接口成功但无 token 字段:不得写入 token,不得当成已登录', async () => {
|
||
const { createLoginState, submitPasswordLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.username = 'admin';
|
||
state.password = '123456';
|
||
|
||
mockEndpoint('/admin/base/open/login', {
|
||
expire: 7200,
|
||
refreshToken: 'should_not_be_used_as_token',
|
||
});
|
||
|
||
const ok = await submitPasswordLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
expect(state.errorMessage.length).toBeGreaterThan(0);
|
||
});
|
||
|
||
it('6.6 接口返回空 token:不得写入本地凭证', async () => {
|
||
const { createLoginState, submitPasswordLogin, completeLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.username = 'admin';
|
||
state.password = '123456';
|
||
|
||
mockEndpoint('/admin/base/open/login', { token: '' });
|
||
const okEmpty = await submitPasswordLogin(state);
|
||
expect(okEmpty).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
|
||
mockEndpoint('/admin/base/open/login', { token: ' ' });
|
||
const okBlank = await submitPasswordLogin(state);
|
||
expect(okBlank).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
|
||
expect(completeLogin('')).toBe(false);
|
||
expect(completeLogin(' ')).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
});
|
||
|
||
it('6.7 账号登录网络失败:不得写入 token', async () => {
|
||
mockByUrl.set('/admin/base/open/login', {
|
||
failError: { errMsg: 'network error' },
|
||
});
|
||
const { createLoginState, submitPasswordLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.username = 'admin';
|
||
state.password = '123456';
|
||
|
||
const ok = await submitPasswordLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
});
|
||
|
||
it('6.8 账号登录 HTTP 非成功:不得写入 token', async () => {
|
||
mockByUrl.set('/admin/base/open/login', {
|
||
statusCode: 500,
|
||
data: { message: 'Internal Server Error' },
|
||
});
|
||
const { createLoginState, submitPasswordLogin } = loadUseLogin();
|
||
const state = createLoginState();
|
||
state.username = 'admin';
|
||
state.password = '123456';
|
||
|
||
const ok = await submitPasswordLogin(state);
|
||
|
||
expect(ok).toBe(false);
|
||
expect(storageMap.has('token')).toBe(false);
|
||
expect(switchTabCount).toBe(0);
|
||
});
|
||
});
|
||
});
|
||
|