@eohjsc/react-native-smart-city 0.3.75 → 0.3.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commons/Action/ItemQuickAction.js +78 -74
- package/src/hooks/IoT/useBluetoothConnection.js +10 -5
- package/src/iot/RemoteControl/Bluetooth.js +44 -33
- package/src/iot/RemoteControl/__test__/Bluetooth.test.js +33 -33
- package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +1 -1
- package/src/screens/SubUnit/AddSubUnit.js +29 -15
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +42 -0
- package/src/screens/Unit/AddMenu.js +4 -1
package/package.json
CHANGED
|
@@ -6,89 +6,93 @@ import { useRemoteControl } from '../../hooks/IoT';
|
|
|
6
6
|
import { useConfigGlobalState } from '../../iot/states';
|
|
7
7
|
import IconComponent from '../IconComponent';
|
|
8
8
|
|
|
9
|
-
const ItemQuickAction = memo(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const ItemQuickAction = memo(
|
|
10
|
+
({ sensor, wrapperStyle, setStatus, iconSize = 40 }) => {
|
|
11
|
+
const [isSendingCommand, setIsSendingCommand] = useState(false);
|
|
12
|
+
const [action, setAction] = useState(sensor.action);
|
|
13
|
+
// eslint-disable-next-line no-unused-vars
|
|
14
|
+
const [configValues, _] = useConfigGlobalState('configValues');
|
|
15
|
+
const [isOn, setIsOn] = useState(false);
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
const sendRemoteCommand = useRemoteControl();
|
|
18
|
+
const [processing, setProcessing] = useState(false);
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (!sensor.quick_action) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!(sensor.quick_action?.config_id in configValues)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const configValue = configValues[sensor.quick_action.config_id];
|
|
25
|
+
setIsOn(configValue?.value);
|
|
26
|
+
}, [sensor, configValues]);
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
setAction(sensor.quick_action.on_action);
|
|
37
|
-
setStatus && setStatus(sensor.quick_action.off_status);
|
|
38
|
-
}
|
|
39
|
-
}, [isOn, setStatus, sensor.quick_action]);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!sensor.quick_action) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
setProcessing(true);
|
|
47
|
-
let data = null;
|
|
48
|
-
if (
|
|
49
|
-
action?.allow_config_store_value_id === sensor?.quick_action?.config_id
|
|
50
|
-
) {
|
|
51
|
-
if (action?.name?.toLowerCase().includes('off')) {
|
|
52
|
-
data = {
|
|
53
|
-
config_id: action?.allow_config_store_value_id,
|
|
54
|
-
config_value: 0,
|
|
55
|
-
};
|
|
33
|
+
if (isOn) {
|
|
34
|
+
setAction(sensor.quick_action.off_action);
|
|
35
|
+
setStatus && setStatus(sensor.quick_action.on_status);
|
|
56
36
|
} else {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
config_value: 1,
|
|
60
|
-
};
|
|
37
|
+
setAction(sensor.quick_action.on_action);
|
|
38
|
+
setStatus && setStatus(sensor.quick_action.off_status);
|
|
61
39
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
40
|
+
}, [isOn, setStatus, sensor.quick_action]);
|
|
41
|
+
|
|
42
|
+
const userId = useSCContextSelector((state) => state?.auth.account.user.id);
|
|
43
|
+
const onActionPress = useCallback(async () => {
|
|
44
|
+
if (processing) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
setProcessing(true);
|
|
48
|
+
let data = null;
|
|
49
|
+
if (
|
|
50
|
+
action?.allow_config_store_value_id === sensor?.quick_action?.config_id
|
|
51
|
+
) {
|
|
52
|
+
if (action?.name?.toLowerCase().includes('off')) {
|
|
53
|
+
data = {
|
|
54
|
+
config_id: action?.allow_config_store_value_id,
|
|
55
|
+
config_value: 0,
|
|
56
|
+
};
|
|
57
|
+
} else {
|
|
58
|
+
data = {
|
|
59
|
+
config_id: action?.allow_config_store_value_id,
|
|
60
|
+
config_value: 1,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
data = JSON.stringify(data);
|
|
64
|
+
}
|
|
65
|
+
await sendRemoteCommand(sensor, action, data, userId);
|
|
66
|
+
setIsSendingCommand(true);
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
if (!sensor.quick_action.will_auto_update_status) {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
setIsOn(action.id === sensor.quick_action.on_action.id);
|
|
71
|
+
}, sensor.quick_action.interval);
|
|
72
|
+
}
|
|
73
|
+
setProcessing(false);
|
|
74
|
+
}, [processing, action, sensor, sendRemoteCommand, userId]);
|
|
75
|
+
|
|
76
|
+
if (!action) {
|
|
77
|
+
return <View />;
|
|
71
78
|
}
|
|
72
|
-
setProcessing(false);
|
|
73
|
-
}, [processing, action, sensor, sendRemoteCommand, userId]);
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
return (
|
|
81
|
+
<TouchableOpacity
|
|
82
|
+
accessibilityLabel={`${AccessibilityLabel.ITEM_QUICK_ACTION_PRESS}-${sensor?.id}`}
|
|
83
|
+
onPress={onActionPress}
|
|
84
|
+
>
|
|
85
|
+
<View style={wrapperStyle}>
|
|
86
|
+
<IconComponent
|
|
87
|
+
icon={action?.icon_kit || action?.icon || 'PoweroffOutlined'}
|
|
88
|
+
isSendingCommand={isSendingCommand}
|
|
89
|
+
iconSize={iconSize}
|
|
90
|
+
size={iconSize}
|
|
91
|
+
/>
|
|
92
|
+
</View>
|
|
93
|
+
</TouchableOpacity>
|
|
94
|
+
);
|
|
77
95
|
}
|
|
78
|
-
|
|
79
|
-
return (
|
|
80
|
-
<TouchableOpacity
|
|
81
|
-
accessibilityLabel={`${AccessibilityLabel.ITEM_QUICK_ACTION_PRESS}-${sensor?.id}`}
|
|
82
|
-
onPress={onActionPress}
|
|
83
|
-
>
|
|
84
|
-
<View style={wrapperStyle}>
|
|
85
|
-
<IconComponent
|
|
86
|
-
icon={action?.icon_kit || action?.icon || 'PoweroffOutlined'}
|
|
87
|
-
isSendingCommand={isSendingCommand}
|
|
88
|
-
/>
|
|
89
|
-
</View>
|
|
90
|
-
</TouchableOpacity>
|
|
91
|
-
);
|
|
92
|
-
});
|
|
96
|
+
);
|
|
93
97
|
|
|
94
98
|
export default ItemQuickAction;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { useContext, useCallback, useRef, useEffect } from 'react';
|
|
1
|
+
import { useContext, useCallback, useRef, useEffect, useMemo } from 'react';
|
|
2
2
|
import { AppState, Platform } from 'react-native';
|
|
3
|
+
import { getSystemVersion } from 'react-native-device-info';
|
|
4
|
+
|
|
3
5
|
import { SCContext, useSCContextSelector } from '../../context';
|
|
4
6
|
import { Action } from '../../context/actionType';
|
|
5
7
|
import { scanBluetoothDevices } from '../../iot/RemoteControl/Bluetooth';
|
|
@@ -8,6 +10,7 @@ import { OpenSetting } from '../../utils/Permission/common';
|
|
|
8
10
|
import { useTranslations } from '../Common/useTranslations';
|
|
9
11
|
import { SCConfig } from '../../configs';
|
|
10
12
|
|
|
13
|
+
// These permissions are only for android 12
|
|
11
14
|
const permissions = [
|
|
12
15
|
'android.permission.BLUETOOTH_CONNECT',
|
|
13
16
|
'android.permission.BLUETOOTH_SCAN',
|
|
@@ -24,11 +27,13 @@ const useBluetoothConnection = (fnCallback) => {
|
|
|
24
27
|
const permissionsRequested = useSCContextSelector(
|
|
25
28
|
(state) => state.bluetooth.permissionsRequested
|
|
26
29
|
);
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
|
|
31
|
+
const permissionsGranted = useMemo(() => {
|
|
32
|
+
return Platform.OS === 'ios' || parseInt(getSystemVersion(), 10) < 12
|
|
29
33
|
? true
|
|
30
34
|
: // eslint-disable-next-line react-hooks/rules-of-hooks
|
|
31
35
|
useSCContextSelector((state) => state.bluetooth.permissionsGranted);
|
|
36
|
+
}, []);
|
|
32
37
|
|
|
33
38
|
const onDeviceFound = useCallback(async (name, device) => {
|
|
34
39
|
fnCallback && fnCallback({ name, device });
|
|
@@ -38,9 +43,9 @@ const useBluetoothConnection = (fnCallback) => {
|
|
|
38
43
|
|
|
39
44
|
const bluetoothScanDevices = useCallback(
|
|
40
45
|
(addresses) => {
|
|
41
|
-
|
|
46
|
+
scanBluetoothDevices(addresses, onDeviceFound);
|
|
42
47
|
},
|
|
43
|
-
[
|
|
48
|
+
[onDeviceFound]
|
|
44
49
|
);
|
|
45
50
|
|
|
46
51
|
useEffect(() => {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/* eslint-disable promise/prefer-await-to-callbacks */
|
|
2
|
-
import { BLE } from '../../configs';
|
|
3
|
-
import t from '../../hooks/Common/useTranslations';
|
|
4
2
|
import base64 from 'react-native-base64';
|
|
5
|
-
import { BleManager } from 'react-native-ble-plx';
|
|
3
|
+
import { BleManager, ScanMode } from 'react-native-ble-plx';
|
|
6
4
|
import { ToastBottomHelper } from '../../utils/Utils';
|
|
7
5
|
|
|
6
|
+
import { BLE } from '../../configs';
|
|
7
|
+
import t from '../../hooks/Common/useTranslations';
|
|
8
|
+
|
|
8
9
|
const bluetoothDevices = {};
|
|
9
10
|
const needToScanDevices = [];
|
|
10
11
|
const bleManager = new BleManager();
|
|
11
12
|
|
|
13
|
+
let isScanning = false;
|
|
14
|
+
|
|
12
15
|
export const SEND_COMMAND_OVER_BLUETOOTH_FAIL =
|
|
13
16
|
'SEND_COMMAND_OVER_BLUETOOTH_FAIL';
|
|
14
17
|
|
|
@@ -36,44 +39,52 @@ export const realScanBluetoothDevices = async (onDeviceFound) => {
|
|
|
36
39
|
if (!needToScanDevices.length) {
|
|
37
40
|
return;
|
|
38
41
|
}
|
|
42
|
+
if (!isScanning) {
|
|
43
|
+
isScanning = true;
|
|
44
|
+
bleManager.startDeviceScan(
|
|
45
|
+
null,
|
|
46
|
+
{ scanMode: ScanMode?.Balanced },
|
|
47
|
+
(error, device) => {
|
|
48
|
+
if (error) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
) {
|
|
55
|
-
name = device.localName;
|
|
56
|
-
} else {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
52
|
+
let name = null;
|
|
53
|
+
if (
|
|
54
|
+
needToScanDevices.includes(device.name) &&
|
|
55
|
+
!bluetoothDevices[device.name]
|
|
56
|
+
) {
|
|
57
|
+
name = device.name;
|
|
58
|
+
} else if (
|
|
59
|
+
needToScanDevices.includes(device.localName) &&
|
|
60
|
+
!bluetoothDevices[device.localName]
|
|
61
|
+
) {
|
|
62
|
+
name = device.localName;
|
|
63
|
+
} else {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
59
66
|
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
const index = needToScanDevices.indexOf(name);
|
|
68
|
+
needToScanDevices.splice(index, 1);
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
bluetoothDevices[name] = device;
|
|
71
|
+
onDeviceFound && onDeviceFound(name, device);
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
if (!needToScanDevices.length) {
|
|
74
|
+
try {
|
|
75
|
+
bleManager.stopDeviceScan();
|
|
76
|
+
isScanning = false;
|
|
77
|
+
// eslint-disable-next-line no-empty
|
|
78
|
+
} catch {}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
}
|
|
73
83
|
|
|
74
84
|
const to = setTimeout(() => {
|
|
75
85
|
try {
|
|
76
86
|
bleManager.stopDeviceScan();
|
|
87
|
+
isScanning = false;
|
|
77
88
|
clearTimeout(to);
|
|
78
89
|
// eslint-disable-next-line no-empty
|
|
79
90
|
} catch {}
|
|
@@ -25,6 +25,36 @@ describe('Test IOT Bluetooth', () => {
|
|
|
25
25
|
clearNeedToScanDevices();
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
it('Send command over bluetooth via device success', async () => {
|
|
29
|
+
const device = {
|
|
30
|
+
name: '1234567',
|
|
31
|
+
cancelConnection: jest.fn(),
|
|
32
|
+
connect: async () => ({
|
|
33
|
+
discoverAllServicesAndCharacteristics: async () => ({
|
|
34
|
+
writeCharacteristicWithResponseForService: async () => ({}),
|
|
35
|
+
monitorCharacteristicForService: async () => ({}),
|
|
36
|
+
}),
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
bleManager.startDeviceScan.mockImplementation(
|
|
40
|
+
(uuids, options, listener) => {
|
|
41
|
+
listener(null, device);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
await scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
45
|
+
|
|
46
|
+
await sendCommandOverBluetooth(
|
|
47
|
+
{
|
|
48
|
+
remote_control_options: {
|
|
49
|
+
bluetooth: {
|
|
50
|
+
address: device.name,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{}
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
28
58
|
test('Scan bluetooth device will init hardware scan', async () => {
|
|
29
59
|
await scanBluetoothDevices(['123456'], mockOnDeviceFound);
|
|
30
60
|
expect(bleManager.startDeviceScan).toBeCalled();
|
|
@@ -107,7 +137,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
107
137
|
}
|
|
108
138
|
);
|
|
109
139
|
await scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
110
|
-
expect(bleManager.stopDeviceScan).toBeCalled();
|
|
140
|
+
expect(bleManager.stopDeviceScan).not.toBeCalled();
|
|
111
141
|
});
|
|
112
142
|
|
|
113
143
|
it('Scan same device again will not trigger hardware scan', async () => {
|
|
@@ -120,7 +150,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
120
150
|
}
|
|
121
151
|
);
|
|
122
152
|
await scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
123
|
-
expect(bleManager.startDeviceScan).toBeCalled();
|
|
153
|
+
expect(bleManager.startDeviceScan).not.toBeCalled();
|
|
124
154
|
|
|
125
155
|
bleManager.startDeviceScan.mockClear();
|
|
126
156
|
|
|
@@ -169,37 +199,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
169
199
|
},
|
|
170
200
|
},
|
|
171
201
|
},
|
|
172
|
-
|
|
173
|
-
);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('Send command over bluetooth via device success', async () => {
|
|
177
|
-
const device = {
|
|
178
|
-
name: '1234567',
|
|
179
|
-
cancelConnection: jest.fn(),
|
|
180
|
-
connect: async () => ({
|
|
181
|
-
discoverAllServicesAndCharacteristics: async () => ({
|
|
182
|
-
writeCharacteristicWithResponseForService: async () => ({}),
|
|
183
|
-
monitorCharacteristicForService: async () => ({}),
|
|
184
|
-
}),
|
|
185
|
-
}),
|
|
186
|
-
};
|
|
187
|
-
bleManager.startDeviceScan.mockImplementation(
|
|
188
|
-
(uuids, options, listener) => {
|
|
189
|
-
listener(null, device);
|
|
190
|
-
}
|
|
191
|
-
);
|
|
192
|
-
await scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
193
|
-
|
|
194
|
-
await sendCommandOverBluetooth(
|
|
195
|
-
{
|
|
196
|
-
remote_control_options: {
|
|
197
|
-
bluetooth: {
|
|
198
|
-
address: device.name,
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
{}
|
|
202
|
+
undefined
|
|
203
203
|
);
|
|
204
204
|
});
|
|
205
205
|
});
|
|
@@ -25,7 +25,13 @@ const AddSubUnit = ({ route }) => {
|
|
|
25
25
|
const t = useTranslations();
|
|
26
26
|
const { dismissKeyboard } = useKeyboardShow();
|
|
27
27
|
const { navigate, goBack, dispatch } = useNavigation();
|
|
28
|
-
const {
|
|
28
|
+
const {
|
|
29
|
+
unit,
|
|
30
|
+
addType,
|
|
31
|
+
isAddUnit,
|
|
32
|
+
location = '',
|
|
33
|
+
isInsideUnit,
|
|
34
|
+
} = route?.params;
|
|
29
35
|
const [roomName, setRoomName] = useState('');
|
|
30
36
|
const [wallpaper, setWallpaper] = useState('');
|
|
31
37
|
const [imageUrl, setImageUrl] = useState('');
|
|
@@ -94,18 +100,25 @@ const AddSubUnit = ({ route }) => {
|
|
|
94
100
|
});
|
|
95
101
|
return;
|
|
96
102
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
})
|
|
108
|
-
|
|
103
|
+
const commonPrams = {
|
|
104
|
+
unitId: unit.id,
|
|
105
|
+
unitData: unit,
|
|
106
|
+
stationId: data.id,
|
|
107
|
+
isAddSubUnit: true,
|
|
108
|
+
routeName: Routes.DashboardStack,
|
|
109
|
+
};
|
|
110
|
+
if (isInsideUnit) {
|
|
111
|
+
navigate(Routes.UnitDetail, {
|
|
112
|
+
params: commonPrams,
|
|
113
|
+
});
|
|
114
|
+
} else {
|
|
115
|
+
dispatch(
|
|
116
|
+
replace(Routes.UnitStack, {
|
|
117
|
+
screen: Routes.UnitDetail,
|
|
118
|
+
params: commonPrams,
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
}
|
|
109
122
|
cleanData();
|
|
110
123
|
} else {
|
|
111
124
|
awaitCreate.current = false;
|
|
@@ -118,12 +131,13 @@ const AddSubUnit = ({ route }) => {
|
|
|
118
131
|
roomName,
|
|
119
132
|
location,
|
|
120
133
|
wallpaper,
|
|
121
|
-
|
|
134
|
+
dispatch,
|
|
122
135
|
t,
|
|
123
136
|
unit,
|
|
124
137
|
addType,
|
|
125
|
-
|
|
138
|
+
isInsideUnit,
|
|
126
139
|
goBack,
|
|
140
|
+
navigate,
|
|
127
141
|
route.params,
|
|
128
142
|
]);
|
|
129
143
|
|
|
@@ -251,6 +251,48 @@ describe('Test AddSubUnit', () => {
|
|
|
251
251
|
});
|
|
252
252
|
});
|
|
253
253
|
|
|
254
|
+
it('test create sub-unit is in side Unit', async () => {
|
|
255
|
+
route.params = {
|
|
256
|
+
...route.params,
|
|
257
|
+
isInsideUnit: true,
|
|
258
|
+
};
|
|
259
|
+
mock.onPost(API.SUB_UNIT.CREATE_SUB_UNIT(1)).reply(200, {});
|
|
260
|
+
await act(async () => {
|
|
261
|
+
tree = await create(wrapComponent(route));
|
|
262
|
+
});
|
|
263
|
+
const instance = tree.root;
|
|
264
|
+
const viewButtonBottom = await makeValidateData(instance);
|
|
265
|
+
await act(async () => {
|
|
266
|
+
await viewButtonBottom.props.onRightClick();
|
|
267
|
+
});
|
|
268
|
+
expect(mockedNavigate).toHaveBeenCalledWith('UnitDetail', {
|
|
269
|
+
params: {
|
|
270
|
+
isAddSubUnit: true,
|
|
271
|
+
routeName: 'DashboardStack',
|
|
272
|
+
stationId: undefined,
|
|
273
|
+
unitData: { id: 1, name: 'Unit name' },
|
|
274
|
+
unitId: 1,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('test create sub-unit is out side Unit', async () => {
|
|
280
|
+
route.params = {
|
|
281
|
+
...route.params,
|
|
282
|
+
isInsideUnit: false,
|
|
283
|
+
};
|
|
284
|
+
mock.onPost(API.SUB_UNIT.CREATE_SUB_UNIT(1)).reply(200, {});
|
|
285
|
+
await act(async () => {
|
|
286
|
+
tree = await create(wrapComponent(route));
|
|
287
|
+
});
|
|
288
|
+
const instance = tree.root;
|
|
289
|
+
const viewButtonBottom = await makeValidateData(instance);
|
|
290
|
+
await act(async () => {
|
|
291
|
+
await viewButtonBottom.props.onRightClick();
|
|
292
|
+
});
|
|
293
|
+
expect(mockNavigationDispatch).toBeCalledWith(mockReplace);
|
|
294
|
+
});
|
|
295
|
+
|
|
254
296
|
it('test create sub-unit type AddHassiDevice', async () => {
|
|
255
297
|
route.params = {
|
|
256
298
|
...route.params,
|
|
@@ -28,7 +28,10 @@ const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
|
|
|
28
28
|
route: Routes.AddSubUnitStack,
|
|
29
29
|
text: t('sub_unit'),
|
|
30
30
|
image: <AddSubUnitIcon width={43} height={43} />,
|
|
31
|
-
data: {
|
|
31
|
+
data: {
|
|
32
|
+
screen: Routes.AddSubUnit,
|
|
33
|
+
params: { unit, isInsideUnit: true },
|
|
34
|
+
},
|
|
32
35
|
},
|
|
33
36
|
{
|
|
34
37
|
id: 'add_member',
|