已开启
test:add demo for react-native-community-netinfo #1943
linsanjiu创建于 11 天前
test:add demo for react-native-community-netinfo #1943
已开启
linsanjiu创建于 11 天前
2 个文件变更+175-277
@@ -1,69 +1,79 @@
1-import React from "react";1+import React from 'react';
2-import { View, Text, ScrollView, Button } from "react-native";2+import { View, Text, ScrollView, Button } from 'react-native';
3-import NetInfo, { useNetInfo, useNetInfoInstance, NetInfoSubscription } from "@react-native-community/netinfo";3+import NetInfo, { useNetInfo, useNetInfoInstance, NetInfoSubscription } from '@react-native-community/netinfo';
4import { Tester, TestSuite, TestCase } from '@rnoh/testerino';4import { Tester, TestSuite, TestCase } from '@rnoh/testerino';
5+import { NetInfoStatePanel } from './shared';
5 6 
6export const NetInfoTest = () => {7export const NetInfoTest = () => {
7- const [InstanceState, setInstanceState] = React.useState<any>({});8+ const mountedRef = React.useRef(true);
9+ const subscriptionRef = React.useRef<NetInfoSubscription | null>(null);
8 10 
11+ const [InstanceState, setInstanceState] = React.useState<any>({});
9 const netInfoInstance = useNetInfoInstance(false);12 const netInfoInstance = useNetInfoInstance(false);
10- const getInstanceState = () => {
11- setInstanceState(netInfoInstance.netInfo)
12- }
13- const instanceRefrech = async () => {
14- await netInfoInstance.refresh()
15- setInstanceState(netInfoInstance.netInfo)
16- }
17 13 
18 const [netInfoState, setNetInfoState] = React.useState<any>({});14 const [netInfoState, setNetInfoState] = React.useState<any>({});
19- const fetch = async () => {
20- console.log('拿到数据啦!!!!!');
21- const fetchState = await NetInfo.fetch()
22- setNetInfoState(fetchState)
23- }
24- const refresh = async () => {
25- console.log('数据刷新啦!!!!!');
26- const refreshState = await NetInfo.refresh();
27- setNetInfoState(refreshState)
28- }
29- 
30- // 管理 addEventListener 订阅
31- const [subscription, setSubscription] = React.useState<NetInfoSubscription | null>(null);
32- const toListen = () => {
33- // 先取消之前的订阅,避免重复监听
34- if (subscription) {
35- subscription();
36- }
37- const newSubscription = NetInfo.addEventListener((listenerState) => {
38- console.log('监听到数据更新啦!!!!!');
39- setNetInfoState(listenerState)
40- });
41- setSubscription(() => newSubscription);
42- console.log('addEventListener 订阅成功');
43- }
44- const removeListener = () => {
45- if (subscription) {
46- subscription();
47- setSubscription(null);
48- console.log('addEventListener 取消订阅成功');
49- }
50- }
51- // 组件卸载时清理订阅
52- React.useEffect(() => {
53- return () => {
54- if (subscription) {
55- subscription();
56- }
57- };
58- }, [subscription]);
59- 
60 const [netUseInfoState, setUseNetInfoState] = React.useState<any>({});15 const [netUseInfoState, setUseNetInfoState] = React.useState<any>({});
61- let netInfo = useNetInfo();16+ const netInfo = useNetInfo();
17+ 
18+ React.useEffect(() => {
19+ mountedRef.current = true;
20+ return () => {
21+ mountedRef.current = false;
22+ subscriptionRef.current?.();
23+ subscriptionRef.current = null;
24+ };
25+ }, []);
26+ 
27+ const getInstanceState = () => {
28+ setInstanceState(netInfoInstance.netInfo);
29+ };
30+ 
31+ const instanceRefresh = async () => {
32+ netInfoInstance.refresh();
cpf-manager
cpf-managercpf-manager10 天前

【AI-Review】【一般】【基础代码问题】【代码逻辑错误】instanceRefresh 移除了 await,引入时序风险

● 问题:在 NetInfoTest.tsx:32instanceRefresh 函数中,netInfoInstance.refresh() 被调用但未 await,随后通过固定 300ms 超时(line 33)等待。对比 base 版本的实现 await netInfoInstance.refresh(),本 PR 将 await 替换为固定 300ms 超时。useNetInfoInstance 返回的 refresh 返回 Promise<NetInfoState>,在慢速设备上 300ms 内可能未完成,line 37 的 setInstanceState(netInfoInstance.netInfo) 将读取到刷新前的旧状态,用户点击"instanceRefresh"按钮后 UI 仍显示旧数据。

● 影响:用户点击"instanceRefresh"按钮后,若原生模块在 300ms 内未完成刷新,UI 显示的网络状态仍为刷新前的值,功能表现与用户预期不一致。此外 refresh() 返回的 Promise 未被 await 也未 .catch(),若原生模块抛出异常将产生未处理的 Promise rejection。

● 建议:恢复 await 写法,直接使用 refresh 的返回值更新状态:

const instanceRefresh = async () => {
  try {
    const state = await netInfoInstance.refresh();
    if (!mountedRef.current) { return; }
    setInstanceState(state);
  } catch (error) {
    if (!mountedRef.current) { return; }
    setInstanceState(netInfoInstance.netInfo);
  }
};
likedislike
33+ await new Promise((resolve) => setTimeout(resolve, 300));
34+ if (!mountedRef.current) {
35+ return;
36+ }
37+ setInstanceState(netInfoInstance.netInfo);
38+ };
39+ 
40+ const fetch = async () => {
41+ const fetchState = await NetInfo.fetch();
cpf-manager
cpf-managercpf-manager7 天前

【AI-Review】【一般】【基础代码问题】【异常处理】fetch 和 refresh 未捕获 Promise reject

● 问题:fetch 函数(NetInfoTest.tsx:40-46)的 await NetInfo.fetch()refresh 函数(NetInfoTest.tsx:48-54)的 await NetInfo.refresh() 均未使用 try/catch 包裹。当 NetInfo 原生模块调用失败(如模块未注册、权限不足、原生侧抛异常)导致 Promise reject 时,异常作为未处理的 Promise rejection 冒泡。触发路径:用户点击 "fetch" 或 "refresh" 按钮 → onPress 调用 fetch()/refresh() → NetInfo.fetch()/refresh() reject → await 抛出异常 → async 函数返回 rejected Promise → onPress 未捕获 → 未处理的 Promise rejection。

● 影响:一般。Dev 模式下弹出 yellow/red box 警告干扰测试;在生产环境的特定 Promise rejection 处理配置下可能触发应用异常退出。测试页面不会显示错误信息,用户无法判断操作失败原因。

● 建议:用 try/catch 包裹 await 调用,在 catch 分支更新状态以提示失败:

const fetch = async () => {
  try {
    const fetchState = await NetInfo.fetch();
    if (!mountedRef.current) { return; }
    setNetInfoState(fetchState);
  } catch (error) {
    if (!mountedRef.current) { return; }
    setNetInfoState({ type: 'unknown', error: String(error) });
  }
};

refresh 函数同理。

likedislike
42+ if (!mountedRef.current) {
43+ return;
44+ }
45+ setNetInfoState(fetchState);
46+ };
47+ 
48+ const refresh = async () => {
49+ const refreshState = await NetInfo.refresh();
50+ if (!mountedRef.current) {
51+ return;
52+ }
53+ setNetInfoState(refreshState);
54+ };
55+ 
56+ const toListen = () => {
57+ subscriptionRef.current?.();
58+ subscriptionRef.current = NetInfo.addEventListener((listenerState) => {
59+ if (!mountedRef.current) {
60+ return;
61+ }
62+ setNetInfoState(listenerState);
63+ });
64+ };
65+ 
66+ const removeListener = () => {
67+ if (subscriptionRef.current) {
68+ subscriptionRef.current();
69+ subscriptionRef.current = null;
70+ }
71+ };
72+ 
62 const getUseNetInfo = () => {73 const getUseNetInfo = () => {
63 setUseNetInfoState(netInfo);74 setUseNetInfoState(netInfo);
64- }75+ };
65 76 
66- // 枚举值说明数据
67 const netInfoStateTypeDesc = [77 const netInfoStateTypeDesc = [
68 { value: 'unknown', desc: '网络状态未知或尚未确定' },78 { value: 'unknown', desc: '网络状态未知或尚未确定' },
69 { value: 'none', desc: '无活动的网络连接' },79 { value: 'none', desc: '无活动的网络连接' },
@@ -83,7 +93,6 @@ export const NetInfoTest = () => {
83 { value: '5g', desc: '5G蜂窝网络(NRNSA、NR)' },93 { value: '5g', desc: '5G蜂窝网络(NRNSA、NR)' },
84 ];94 ];
85 95 
86- // 平台差异说明
87 const platformNotes = [96 const platformNotes = [
88 'WiFi SSID/BSSID: 需要特定权限,可能无法获取',97 'WiFi SSID/BSSID: 需要特定权限,可能无法获取',
89 '信号强度: 部分设备可能无法准确获取',98 '信号强度: 部分设备可能无法准确获取',
@@ -103,237 +112,54 @@ export const NetInfoTest = () => {
103 <Button title="fetch" onPress={() => fetch()} />112 <Button title="fetch" onPress={() => fetch()} />
104 <Button title="refresh" onPress={() => refresh()} />113 <Button title="refresh" onPress={() => refresh()} />
105 </View>114 </View>
106- <TestCase itShould={'NetInfoState(public)'}>115+ <NetInfoStatePanel state={netInfoState} title="NetInfo" />
107- <View>
108- <Text>Type: {netInfoState?.type}</Text>
109- </View>
110- <View>
111- <Text>isConnected: {JSON.stringify(netInfoState?.isConnected)}</Text>
112- </View>
113- <View>
114- <Text>isInternetReachable: {JSON.stringify(netInfoState?.isInternetReachable)}</Text>
115- </View>
116- <View>
117- <Text>isWifiEnabled: {JSON.stringify(netInfoState?.isWifiEnabled)}</Text>
118- </View>
119- </TestCase>
120- <TestCase itShould={'NetInfoState(details-wifi)'}>
121- <View>
122- <Text>isConnectionExpensive: {JSON.stringify(netInfoState?.details?.isConnectionExpensive)}</Text>
123- </View>
124- <View>
125- <Text>ssid: {JSON.stringify(netInfoState?.details?.ssid)}</Text>
126- </View>
127- <View>
128- <Text>bssid: {JSON.stringify(netInfoState?.details?.bssid)}</Text>
129- </View>
130- <View>
131- <Text>strength: {JSON.stringify(netInfoState?.details?.strength)}</Text>
132- </View>
133- <View>
134- <Text>ipAddress: {JSON.stringify(netInfoState?.details?.ipAddress)}</Text>
135- </View>
136- <View>
137- <Text>subnet: {JSON.stringify(netInfoState?.details?.subnet)}</Text>
138- </View>
139- <View>
140- <Text>frequency: {JSON.stringify(netInfoState?.details?.frequency)}</Text>
141- </View>
142- <View>
143- <Text>linkSpeed: {JSON.stringify(netInfoState?.details?.linkSpeed)}</Text>
144- </View>
145- <View>
146- <Text>rxLinkSpeed: {JSON.stringify(netInfoState?.details?.rxLinkSpeed)}</Text>
147- </View>
148- <View>
149- <Text>txLinkSpeed: {JSON.stringify(netInfoState?.details?.txLinkSpeed)}</Text>
150- </View>
151- </TestCase>
152- <TestCase itShould={'NetInfoState(details-cellular)'}>
153- <View>
154- <Text>isConnectionExpensive: {JSON.stringify(netInfoState?.details?.isConnectionExpensive)}</Text>
155- </View>
156- <View>
157- <Text>cellularGeneration: {JSON.stringify(netInfoState?.details?.cellularGeneration)}</Text>
158- </View>
159- <View>
160- <Text>carrier: {JSON.stringify(netInfoState?.details?.carrier)}</Text>
161- </View>
162- </TestCase>
163- <TestCase itShould={'NetInfoState(details-bluetooth, ethernet, wimax, vpn, or other)'}>
164- <View>
165- <Text>isConnectionExpensive: {JSON.stringify(netInfoState?.details?.isConnectionExpensive)}</Text>
166- </View>
167- </TestCase>
168 </TestSuite>116 </TestSuite>
169 117 
170- <TestSuite name={'NetInfo枚举与平台差异'}>118+ <TestSuite name={'NetInfo枚举与平台差异'}>
171- <TestCase itShould={'枚举值说明 (NetInfoStateType)'}>119+ <TestCase itShould={'枚举值说明 (NetInfoStateType)'}>
172- {netInfoStateTypeDesc.map((item, index) => (120+ {netInfoStateTypeDesc.map((item, index) => (
173- <View key={index} style={{ marginVertical: 2 }}>121+ <View key={index} style={{ marginVertical: 2 }}>
174- <Text style={{ fontSize: 12 }}>- {item.value}: {item.desc}</Text>122+ <Text style={{ fontSize: 12 }}>- {item.value}: {item.desc}</Text>
123+ </View>
124+ ))}
125+ <View style={{ marginTop: 8 }}>
126+ <Text style={{ fontSize: 12, color: '#666' }}>当前网络类型: {netInfoState?.type || '未知'}</Text>
175 </View>127 </View>
176- ))}128+ </TestCase>
177- <View style={{ marginTop: 8 }}>
178- <Text style={{ fontSize: 12, color: '#666' }}>当前网络类型: {netInfoState?.type || '未知'}</Text>
179- </View>
180- </TestCase>
181 129 
182- <TestCase itShould={'枚举值说明 (NetInfoCellularGeneration)'}>130+ <TestCase itShould={'枚举值说明 (NetInfoCellularGeneration)'}>
183- {netInfoCellularGenerationDesc.map((item, index) => (131+ {netInfoCellularGenerationDesc.map((item, index) => (
184- <View key={index} style={{ marginVertical: 2 }}>132+ <View key={index} style={{ marginVertical: 2 }}>
185- <Text style={{ fontSize: 12 }}>- {item.value}: {item.desc}</Text>133+ <Text style={{ fontSize: 12 }}>- {item.value}: {item.desc}</Text>
134+ </View>
135+ ))}
136+ <View style={{ marginTop: 8 }}>
137+ <Text style={{ fontSize: 12, color: '#666' }}>当前蜂窝代数: {netInfoState?.details?.cellularGeneration || '无'}</Text>
186 </View>138 </View>
187- ))}139+ </TestCase>
188- <View style={{ marginTop: 8 }}>
189- <Text style={{ fontSize: 12, color: '#666' }}>当前蜂窝代数: {netInfoState?.details?.cellularGeneration || '无'}</Text>
190- </View>
191- </TestCase>
192 140 
193- <TestCase itShould={'平台差异说明'}>141+ <TestCase itShould={'平台差异说明'}>
194- {platformNotes.map((note, index) => (142+ {platformNotes.map((note, index) => (
195- <View key={index} style={{ marginVertical: 2 }}>143+ <View key={index} style={{ marginVertical: 2 }}>
196- <Text style={{ fontSize: 12 }}>- {note}</Text>144+ <Text style={{ fontSize: 12 }}>- {note}</Text>
197- </View>145+ </View>
198- ))}146+ ))}
199- </TestCase>147+ </TestCase>
200- </TestSuite>148+ </TestSuite>
201 149 
202 <TestSuite name={'useNetInfo'}>150 <TestSuite name={'useNetInfo'}>
203 <View>151 <View>
204 <Button title="getUseNetInfo" onPress={() => getUseNetInfo()} />152 <Button title="getUseNetInfo" onPress={() => getUseNetInfo()} />
205 </View>153 </View>
206- <TestCase itShould={'NetInfoState(public)'}>154+ <NetInfoStatePanel state={netUseInfoState} title="useNetInfo" />
207- <View>
208- <Text>Type: {netUseInfoState?.type}</Text>
209- </View>
210- <View>
211- <Text>isConnected: {JSON.stringify(netUseInfoState?.isConnected)}</Text>
212- </View>
213- <View>
214- <Text>isInternetReachable: {JSON.stringify(netUseInfoState?.isInternetReachable)}</Text>
215- </View>
216- <View>
217- <Text>isWifiEnabled: {JSON.stringify(netUseInfoState?.isWifiEnabled)}</Text>
218- </View>
219- </TestCase>
220- <TestCase itShould={'NetInfoState(details-wifi)'}>
221- <View>
222- <Text>isConnectionExpensive: {JSON.stringify(netUseInfoState?.details?.isConnectionExpensive)}</Text>
223- </View>
224- <View>
225- <Text>ssid: {JSON.stringify(netUseInfoState?.details?.ssid)}</Text>
226- </View>
227- <View>
228- <Text>bssid: {JSON.stringify(netUseInfoState?.details?.bssid)}</Text>
229- </View>
230- <View>
231- <Text>strength: {JSON.stringify(netUseInfoState?.details?.strength)}</Text>
232- </View>
233- <View>
234- <Text>ipAddress: {JSON.stringify(netUseInfoState?.details?.ipAddress)}</Text>
235- </View>
236- <View>
237- <Text>subnet: {JSON.stringify(netUseInfoState?.details?.subnet)}</Text>
238- </View>
239- <View>
240- <Text>frequency: {JSON.stringify(netUseInfoState?.details?.frequency)}</Text>
241- </View>
242- <View>
243- <Text>linkSpeed: {JSON.stringify(netUseInfoState?.details?.linkSpeed)}</Text>
244- </View>
245- <View>
246- <Text>rxLinkSpeed: {JSON.stringify(netUseInfoState?.details?.rxLinkSpeed)}</Text>
247- </View>
248- <View>
249- <Text>txLinkSpeed: {JSON.stringify(netUseInfoState?.details?.txLinkSpeed)}</Text>
250- </View>
251- </TestCase>
252- <TestCase itShould={'NetInfoState(details-cellular)'}>
253- <View>
254- <Text>isConnectionExpensive: {JSON.stringify(netUseInfoState?.details?.isConnectionExpensive)}</Text>
255- </View>
256- <View>
257- <Text>cellularGeneration: {JSON.stringify(netUseInfoState?.details?.cellularGeneration)}</Text>
258- </View>
259- <View>
260- <Text>carrier: {JSON.stringify(netUseInfoState?.details?.carrier)}</Text>
261- </View>
262- </TestCase>
263- <TestCase itShould={'NetInfoState(details-bluetooth, ethernet, wimax, vpn, or other)'}>
264- <View>
265- <Text>isConnectionExpensive: {JSON.stringify(netUseInfoState?.details?.isConnectionExpensive)}</Text>
266- </View>
267- </TestCase>
268 </TestSuite>155 </TestSuite>
269 156 
270 <TestSuite name={'useNetInfoInstance'}>157 <TestSuite name={'useNetInfoInstance'}>
271 <View>158 <View>
272 <Button title="getInstanceState" onPress={() => getInstanceState()} />159 <Button title="getInstanceState" onPress={() => getInstanceState()} />
273- <Button title="instanceRefrech" onPress={() => instanceRefrech()} />160+ <Button title="instanceRefresh" onPress={() => instanceRefresh()} />
274 </View>161 </View>
275- <TestCase itShould={'NetInfoState(public)'}>162+ <NetInfoStatePanel state={InstanceState} title="useNetInfoInstance" />
276- <View>
277- <Text>Type: {InstanceState?.type}</Text>
278- </View>
279- <View>
280- <Text>isConnected: {JSON.stringify(InstanceState?.isConnected)}</Text>
281- </View>
282- <View>
283- <Text>isInternetReachable: {JSON.stringify(InstanceState?.isInternetReachable)}</Text>
284- </View>
285- <View>
286- <Text>isWifiEnabled: {JSON.stringify(InstanceState?.isWifiEnabled)}</Text>
287- </View>
288- </TestCase>
289- <TestCase itShould={'NetInfoState(details-wifi)'}>
290- <View>
291- <Text>isConnectionExpensive: {JSON.stringify(InstanceState?.details?.isConnectionExpensive)}</Text>
292- </View>
293- <View>
294- <Text>ssid: {JSON.stringify(InstanceState?.details?.ssid)}</Text>
295- </View>
296- <View>
297- <Text>bssid: {JSON.stringify(InstanceState?.details?.bssid)}</Text>
298- </View>
299- <View>
300- <Text>strength: {JSON.stringify(InstanceState?.details?.strength)}</Text>
301- </View>
302- <View>
303- <Text>ipAddress: {JSON.stringify(InstanceState?.details?.ipAddress)}</Text>
304- </View>
305- <View>
306- <Text>subnet: {JSON.stringify(InstanceState?.details?.subnet)}</Text>
307- </View>
308- <View>
309- <Text>frequency: {JSON.stringify(InstanceState?.details?.frequency)}</Text>
310- </View>
311- <View>
312- <Text>linkSpeed: {JSON.stringify(InstanceState?.details?.linkSpeed)}</Text>
313- </View>
314- <View>
315- <Text>rxLinkSpeed: {JSON.stringify(InstanceState?.details?.rxLinkSpeed)}</Text>
316- </View>
317- <View>
318- <Text>txLinkSpeed: {JSON.stringify(InstanceState?.details?.txLinkSpeed)}</Text>
319- </View>
320- </TestCase>
321- <TestCase itShould={'NetInfoState(details-cellular)'}>
322- <View>
323- <Text>isConnectionExpensive: {JSON.stringify(InstanceState?.details?.isConnectionExpensive)}</Text>
324- </View>
325- <View>
326- <Text>cellularGeneration: {JSON.stringify(InstanceState?.details?.cellularGeneration)}</Text>
327- </View>
328- <View>
329- <Text>carrier: {JSON.stringify(InstanceState?.details?.carrier)}</Text>
330- </View>
331- </TestCase>
332- <TestCase itShould={'NetInfoState(details-bluetooth, ethernet, wimax, vpn, or other)'}>
333- <View>
334- <Text>isConnectionExpensive: {JSON.stringify(InstanceState?.details?.isConnectionExpensive)}</Text>
335- </View>
336- </TestCase>
337 </TestSuite>163 </TestSuite>
338 </Tester>164 </Tester>
339 </View>165 </View>
@@ -345,14 +171,15 @@ export const displayName = 'react-native-community-netinfo';
345export const framework = 'React';171export const framework = 'React';
346export const category = 'basic';172export const category = 'basic';
347export const title = 'react-native-community-netinfo';173export const title = 'react-native-community-netinfo';
348-export const documentationURL = 'https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-community-netinfo.md';174+export const documentationURL =
349-export const description = 'react-native-community-netinfo';175+ 'https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-community-netinfo.md';
176+export const description = 'react-native-community/netinfo';
350 177 
351export const examples = [178export const examples = [
352- {179+ {
353- title: 'react-native-community-netinfo',180+ title: 'react-native-community-netinfo',
354- render: function (): any {181+ render: function (): any {
355- return <NetInfoTest />;182+ return <NetInfoTest />;
356- },
357 },183 },
184+ },
358];185];
@@ -0,0 +1,71 @@
1+import React from 'react';
2+import { View, Text } from 'react-native';
3+import { TestCase } from '@rnoh/testerino';
4+ 
5+/** 手测页字段展示 */
6+export const NetInfoStatePanel = ({ state, title }: { state: any; title: string }) => (
7+ <>
8+ <TestCase itShould={`${title} - NetInfoState(public)`}>
9+ <View>
10+ <Text>Type: {state?.type}</Text>
11+ </View>
12+ <View>
13+ <Text>isConnected: {JSON.stringify(state?.isConnected)}</Text>
14+ </View>
15+ <View>
16+ <Text>isInternetReachable: {JSON.stringify(state?.isInternetReachable)}</Text>
17+ </View>
18+ <View>
19+ <Text>isWifiEnabled: {JSON.stringify(state?.isWifiEnabled)}</Text>
20+ </View>
21+ </TestCase>
22+ <TestCase itShould={`${title} - NetInfoState(details-wifi)`}>
23+ <View>
24+ <Text>isConnectionExpensive: {JSON.stringify(state?.details?.isConnectionExpensive)}</Text>
25+ </View>
26+ <View>
27+ <Text>ssid: {JSON.stringify(state?.details?.ssid)}</Text>
28+ </View>
29+ <View>
30+ <Text>bssid: {JSON.stringify(state?.details?.bssid)}</Text>
31+ </View>
32+ <View>
33+ <Text>strength: {JSON.stringify(state?.details?.strength)}</Text>
34+ </View>
35+ <View>
36+ <Text>ipAddress: {JSON.stringify(state?.details?.ipAddress)}</Text>
37+ </View>
38+ <View>
39+ <Text>subnet: {JSON.stringify(state?.details?.subnet)}</Text>
40+ </View>
41+ <View>
42+ <Text>frequency: {JSON.stringify(state?.details?.frequency)}</Text>
43+ </View>
44+ <View>
45+ <Text>linkSpeed: {JSON.stringify(state?.details?.linkSpeed)}</Text>
46+ </View>
47+ <View>
48+ <Text>rxLinkSpeed: {JSON.stringify(state?.details?.rxLinkSpeed)}</Text>
49+ </View>
50+ <View>
51+ <Text>txLinkSpeed: {JSON.stringify(state?.details?.txLinkSpeed)}</Text>
52+ </View>
53+ </TestCase>
54+ <TestCase itShould={`${title} - NetInfoState(details-cellular)`}>
55+ <View>
56+ <Text>isConnectionExpensive: {JSON.stringify(state?.details?.isConnectionExpensive)}</Text>
57+ </View>
58+ <View>
59+ <Text>cellularGeneration: {JSON.stringify(state?.details?.cellularGeneration)}</Text>
60+ </View>
61+ <View>
62+ <Text>carrier: {JSON.stringify(state?.details?.carrier)}</Text>
63+ </View>
64+ </TestCase>
65+ <TestCase itShould={`${title} - NetInfoState(details-bluetooth, ethernet, wimax, vpn, or other)`}>
66+ <View>
67+ <Text>isConnectionExpensive: {JSON.stringify(state?.details?.isConnectionExpensive)}</Text>
68+ </View>
69+ </TestCase>
70+ </>
71+);