fix: defer mini program phone auth until login

This commit is contained in:
kdletters
2026-05-26 19:59:14 +08:00
parent b388b124da
commit 296a7fced9
10 changed files with 520 additions and 19 deletions

View File

@@ -0,0 +1,149 @@
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import vm from 'node:vm';
import { beforeEach, describe, expect, test, vi } from 'vitest';
const repoRoot = process.cwd();
const pageScriptPath = join(
repoRoot,
'miniprogram',
'pages',
'web-view',
'index.js',
);
type MiniProgramPage = {
data: Record<string, unknown>;
setData: (patch: Record<string, unknown>) => void;
onLoad: (query?: Record<string, string>) => Promise<void>;
};
function createWxMock() {
return {
getStorageSync: vi.fn(() => ''),
getSystemInfoSync: vi.fn(() => ({ platform: 'ios' })),
login: vi.fn(),
navigateBack: vi.fn(),
removeStorageSync: vi.fn(),
request: vi.fn(),
setStorageSync: vi.fn(),
};
}
function loadWebViewPage(
wxMock: ReturnType<typeof createWxMock>,
configOverrides: Record<string, unknown> = {},
) {
let pageConfig: Record<string, unknown> | null = null;
const source = readFileSync(pageScriptPath, 'utf8');
const sandbox = {
console,
getCurrentPages: () => [],
module: { exports: {} },
Page(config: Record<string, unknown>) {
pageConfig = config;
},
require(requestPath: string) {
if (requestPath === '../../config') {
return {
API_BASE_URL: 'https://www.genarrative.world/',
MINI_PROGRAM_APP_ID: 'wx-test-app',
MINI_PROGRAM_ENV: 'release',
WEB_VIEW_ENTRY_URL: 'https://www.genarrative.world/',
WEB_VIEW_SOURCE_QUERY: {
clientType: 'mini_program',
clientRuntime: 'wechat_mini_program',
},
...configOverrides,
};
}
throw new Error(`Unexpected require: ${requestPath}`);
},
wx: wxMock,
};
vm.runInNewContext(source, sandbox, { filename: pageScriptPath });
if (!pageConfig) {
throw new Error('web-view page did not call Page()');
}
const page = {
...pageConfig,
data: { ...(pageConfig.data as Record<string, unknown>) },
setData(patch: Record<string, unknown>) {
Object.assign(this.data, patch);
},
} as MiniProgramPage;
return page;
}
describe('mini-program web-view auth page', () => {
beforeEach(() => {
vi.clearAllMocks();
});
test('默认进入时直接打开 web-view不触发微信登录请求', async () => {
const wxMock = createWxMock();
const page = loadWebViewPage(wxMock);
await page.onLoad({});
expect(wxMock.login).not.toHaveBeenCalled();
expect(wxMock.request).not.toHaveBeenCalled();
expect(page.data.loading).toBe(false);
expect(page.data.phoneBindingRequired).toBe(false);
expect(page.data.webViewUrl).toBe(
'https://www.genarrative.world/?clientType=mini_program&clientRuntime=wechat_mini_program',
);
});
test('默认匿名进入 web-view 不依赖 API_BASE_URL 配置', async () => {
const wxMock = createWxMock();
const page = loadWebViewPage(wxMock, {
API_BASE_URL: '',
});
await page.onLoad({});
expect(wxMock.login).not.toHaveBeenCalled();
expect(wxMock.request).not.toHaveBeenCalled();
expect(page.data.errorMessage).toBe('');
expect(page.data.webViewUrl).toBe(
'https://www.genarrative.world/?clientType=mini_program&clientRuntime=wechat_mini_program',
);
});
test('H5 请求登录时才启动微信小程序登录并进入手机号授权态', async () => {
const wxMock = createWxMock();
wxMock.login.mockImplementation(({ success }) => {
success({ code: 'wx-login-code' });
});
wxMock.request.mockImplementation(({ success }) => {
success({
statusCode: 200,
data: {
token: 'jwt-pending-wechat',
bindingStatus: 'pending_bind_phone',
},
});
});
const page = loadWebViewPage(wxMock);
await page.onLoad({ authAction: 'login', returnTo: 'previous' });
expect(wxMock.login).toHaveBeenCalledTimes(1);
expect(wxMock.request).toHaveBeenCalledWith(
expect.objectContaining({
url: 'https://www.genarrative.world/api/auth/wechat/miniprogram-login',
method: 'POST',
data: { code: 'wx-login-code' },
}),
);
expect(page.data.webViewUrl).toBe('');
expect(page.data.loading).toBe(false);
expect(page.data.phoneBindingRequired).toBe(true);
});
});