Tighten WeChat OAuth capability mode selection

This commit is contained in:
IanShaw027
2026-04-21 00:46:40 +08:00
parent 12f4af742f
commit 067eb23d8e
15 changed files with 317 additions and 28 deletions

View File

@@ -14,8 +14,10 @@ const {
setTokenMock,
showSuccessMock,
showErrorMock,
fetchPublicSettingsMock,
routeState,
locationState,
appStoreState,
} = vi.hoisted(() => ({
exchangePendingOAuthCompletionMock: vi.fn(),
completeWeChatOAuthRegistrationMock: vi.fn(),
@@ -28,6 +30,7 @@ const {
setTokenMock: vi.fn(),
showSuccessMock: vi.fn(),
showErrorMock: vi.fn(),
fetchPublicSettingsMock: vi.fn(),
routeState: {
query: {} as Record<string, unknown>,
},
@@ -39,6 +42,10 @@ const {
pathname: '/auth/wechat/callback'
} as { href: string; hash: string; search: string; pathname: string },
},
appStoreState: {
cachedPublicSettings: null as null | Record<string, unknown>,
publicSettingsLoaded: false,
},
}))
vi.mock('vue-router', () => ({
@@ -102,8 +109,10 @@ vi.mock('@/stores', () => ({
setToken: setTokenMock,
}),
useAppStore: () => ({
...appStoreState,
showSuccess: showSuccessMock,
showError: showErrorMock,
fetchPublicSettings: fetchPublicSettingsMock,
}),
}))
@@ -139,7 +148,10 @@ describe('WechatCallbackView', () => {
showErrorMock.mockReset()
prepareOAuthBindAccessTokenCookieMock.mockReset()
getAuthTokenMock.mockReset()
fetchPublicSettingsMock.mockReset()
routeState.query = {}
appStoreState.cachedPublicSettings = null
appStoreState.publicSettingsLoaded = false
localStorage.clear()
locationState.current = {
href: 'http://localhost/auth/wechat/callback',
@@ -157,6 +169,38 @@ describe('WechatCallbackView', () => {
})
})
it('overrides an incompatible query mode with the configured open capability during bind recovery', async () => {
routeState.query = {
wechat_bind_existing: '1',
mode: 'mp',
redirect: '/profile',
}
appStoreState.cachedPublicSettings = {
wechat_oauth_enabled: true,
wechat_oauth_open_enabled: true,
wechat_oauth_mp_enabled: false,
}
appStoreState.publicSettingsLoaded = true
getAuthTokenMock.mockReturnValue('current-auth-token')
mount(WechatCallbackView, {
global: {
stubs: {
AuthLayout: { template: '<div><slot /></div>' },
Icon: true,
RouterLink: { template: '<a><slot /></a>' },
transition: false,
},
},
})
await flushPromises()
expect(prepareOAuthBindAccessTokenCookieMock).toHaveBeenCalledTimes(1)
expect(locationState.current.href).toContain('mode=open')
expect(locationState.current.href).not.toContain('mode=mp')
})
it('does not send adoption decisions during the initial exchange', async () => {
exchangePendingOAuthCompletionMock.mockResolvedValue({
access_token: 'access-token',