import axios, { type InternalAxiosRequestConfig } from 'axios' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { registerAuthRefreshHandler } from './http' import { clearOverseasAccessToken, overseasHttp, replaceOverseasAccessToken } from './overseasHttp' const originalOverseasAdapter = overseasHttp.defaults.adapter function success(config: InternalAxiosRequestConfig, data: unknown) { return Promise.resolve({ status: 200, statusText: 'OK', headers: {}, config, data }) } describe('overseas HTTP client', () => { beforeEach(() => { localStorage.setItem('cc-admin-token', 'domestic-token') clearOverseasAccessToken() registerAuthRefreshHandler(async () => 'domestic-token') }) afterEach(() => { overseasHttp.defaults.adapter = originalOverseasAdapter localStorage.clear() clearOverseasAccessToken() }) it('uses the overseas token supplied by the login session for concurrent requests', async () => { replaceOverseasAccessToken('overseas-token', 900) const authorizations: unknown[] = [] overseasHttp.defaults.adapter = async (config) => { authorizations.push(config.headers.Authorization) return success(config, { code: '200', message: 'success', data: [] }) } await Promise.all([ overseasHttp.get('/platform/v1/last-leg/orders'), overseasHttp.get('/platform/v1/warehouse-admin'), ]) expect(authorizations).toEqual(['Bearer overseas-token', 'Bearer overseas-token']) }) it('refreshes the unified session once and replays once after an overseas 401', async () => { replaceOverseasAccessToken('overseas-1', 900) const refresh = vi.fn(async () => { replaceOverseasAccessToken('overseas-2', 900) return 'domestic-2' }) registerAuthRefreshHandler(refresh) let requests = 0 const authorizations: unknown[] = [] overseasHttp.defaults.adapter = async (config) => { authorizations.push(config.headers.Authorization) if (requests++ === 0) { throw new axios.AxiosError('Unauthorized', 'ERR_BAD_REQUEST', config, undefined, { status: 401, statusText: 'Unauthorized', headers: {}, config, data: { code: 'A0401', message: '海外令牌失效' }, }) } return success(config, { code: '200', message: 'success', data: [] }) } await overseasHttp.get('/platform/v1/last-leg/orders') expect(refresh).toHaveBeenCalledTimes(1) expect(requests).toBe(2) expect(authorizations).toEqual(['Bearer overseas-1', 'Bearer overseas-2']) }) it('refreshes the unified session when no usable overseas token is present', async () => { const refresh = vi.fn(async () => { replaceOverseasAccessToken('overseas-refreshed', 900) return 'domestic-refreshed' }) registerAuthRefreshHandler(refresh) let authorization: unknown overseasHttp.defaults.adapter = async (config) => { authorization = config.headers.Authorization return success(config, { code: '200', message: 'success', data: [] }) } await overseasHttp.get('/platform/v1/last-leg/orders') expect(refresh).toHaveBeenCalledTimes(1) expect(authorization).toBe('Bearer overseas-refreshed') }) it('fails before sending a business request when refresh is domestic-only', async () => { const refresh = vi.fn(async () => 'domestic-only') registerAuthRefreshHandler(refresh) const adapter = vi.fn(async (config: InternalAxiosRequestConfig) => success(config, { code: '200', message: 'success', data: [] })) overseasHttp.defaults.adapter = adapter await expect(overseasHttp.get('/platform/v1/last-leg/orders')).rejects.toThrow('当前环境未签发海外访问令牌') expect(refresh).toHaveBeenCalledTimes(1) expect(adapter).not.toHaveBeenCalled() }) })