071faa482c
纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口 完成项目 TypeScript/Prettier 与 Rust 全量格式化 修复 Pingora expected executable 门禁的空白敏感误报 同步开发运维文档与 AGC skill pack 格式化忽略规则
102 lines
2.8 KiB
TypeScript
102 lines
2.8 KiB
TypeScript
import * as Network from 'expo-network';
|
|
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
|
|
import {
|
|
HOST_BRIDGE_PROTOCOL,
|
|
HOST_BRIDGE_VERSION,
|
|
type HostBridgeRequest,
|
|
} from '../../../../packages/shared/src/contracts/hostBridge';
|
|
import { getMobileHostBridgeNetworkStatus } from './network';
|
|
|
|
vi.mock('expo-network', () => ({
|
|
getNetworkStateAsync: vi.fn(),
|
|
NetworkStateType: {
|
|
CELLULAR: 'CELLULAR',
|
|
NONE: 'NONE',
|
|
WIFI: 'WIFI',
|
|
},
|
|
}));
|
|
|
|
function request(): HostBridgeRequest {
|
|
return {
|
|
bridge: HOST_BRIDGE_PROTOCOL,
|
|
version: HOST_BRIDGE_VERSION,
|
|
id: 'network-request',
|
|
method: 'network.status',
|
|
};
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.mocked(Network.getNetworkStateAsync).mockReset();
|
|
});
|
|
|
|
describe('mobile HostBridge network helper', () => {
|
|
test('wraps Expo Network status in the HostBridge response shape', async () => {
|
|
vi.mocked(Network.getNetworkStateAsync).mockResolvedValue({
|
|
type: Network.NetworkStateType.CELLULAR,
|
|
isConnected: true,
|
|
isInternetReachable: false,
|
|
});
|
|
|
|
await expect(getMobileHostBridgeNetworkStatus(request())).resolves.toEqual({
|
|
bridge: HOST_BRIDGE_PROTOCOL,
|
|
version: HOST_BRIDGE_VERSION,
|
|
id: 'network-request',
|
|
ok: true,
|
|
result: {
|
|
isConnected: true,
|
|
isInternetReachable: false,
|
|
connectionType: 'cellular',
|
|
nativeType: 'CELLULAR',
|
|
},
|
|
});
|
|
});
|
|
|
|
test('normalizes disconnected network state before wrapping response', async () => {
|
|
vi.mocked(Network.getNetworkStateAsync).mockResolvedValue({
|
|
type: Network.NetworkStateType.NONE,
|
|
});
|
|
|
|
await expect(getMobileHostBridgeNetworkStatus(request())).resolves.toEqual({
|
|
bridge: HOST_BRIDGE_PROTOCOL,
|
|
version: HOST_BRIDGE_VERSION,
|
|
id: 'network-request',
|
|
ok: true,
|
|
result: {
|
|
isConnected: false,
|
|
isInternetReachable: null,
|
|
connectionType: 'none',
|
|
nativeType: 'NONE',
|
|
},
|
|
});
|
|
});
|
|
|
|
test('converts native network failures to a stable host_error response', async () => {
|
|
const warnSpy = vi
|
|
.spyOn(console, 'warn')
|
|
.mockImplementation(() => undefined);
|
|
const nativeError = new Error('network query failed');
|
|
vi.mocked(Network.getNetworkStateAsync).mockRejectedValue(nativeError);
|
|
|
|
try {
|
|
await expect(
|
|
getMobileHostBridgeNetworkStatus(request()),
|
|
).resolves.toEqual({
|
|
bridge: HOST_BRIDGE_PROTOCOL,
|
|
version: HOST_BRIDGE_VERSION,
|
|
id: 'network-request',
|
|
ok: false,
|
|
error: {
|
|
code: 'host_error',
|
|
message: 'network status unavailable',
|
|
},
|
|
});
|
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
'mobile network failed for status.query',
|
|
);
|
|
} finally {
|
|
warnSpy.mockRestore();
|
|
}
|
|
});
|
|
});
|