@eohjsc/react-native-smart-city 0.3.32 → 0.3.33
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 +18 -1
- package/src/commons/Action/__test__/ItemQuickAction.test.js +18 -2
- package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +5 -2
- package/src/commons/ActionGroup/OnOffTemplate/index.js +28 -10
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +15 -8
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +19 -5
- package/src/commons/ActionTemplate/OnOffButtonAction.js +14 -5
- package/src/commons/ActionTemplate/__test__/OnOffButtonAction.test.js +23 -2
- package/src/commons/ActionTemplate/__test__/index.test.js +2 -0
- package/src/commons/ActionTemplate/index.js +1 -0
- package/src/commons/Automate/ItemAutomate.js +10 -1
- package/src/commons/OneTapTemplate/NumberUpDownActionTemplate.js +1 -1
- package/src/commons/Tabbar/__test__/index.test.js +97 -0
- package/src/configs/AccessibilityLabel.js +3 -0
- package/src/hoc/__test__/withRemoteControl.test.js +24 -0
- package/src/hooks/Common/__test__/useAndroidTranslucentStatusBar.test.js +55 -0
- package/src/hooks/Common/useDevicesStatus.js +19 -15
- package/src/hooks/__test__/useInitDeepLink.test.js +28 -0
- package/src/hooks/useReceiveNotifications.js +2 -4
- package/src/screens/AddNewAction/SelectAction.js +10 -1
- package/src/screens/ScriptDetail/__test__/index.test.js +35 -34
- package/src/screens/ScriptDetail/index.js +19 -10
- package/src/screens/Sharing/Components/{SensorItem.js → DeviceItem.js} +14 -20
- package/src/screens/Sharing/Components/Styles/{SensorItemStyles.js → DeviceItemStyles.js} +0 -0
- package/src/screens/Sharing/Components/__test__/{SensorItem.test.js → DeviceItem.test.js} +6 -6
- package/src/screens/Sharing/Components/index.js +2 -2
- package/src/screens/Sharing/SelectPermission.js +63 -68
- package/src/screens/Sharing/Styles/SelectPermissionStyles.js +2 -2
- package/src/screens/Sharing/__test__/SelectPermission.test.js +12 -12
- package/src/utils/Utils.js +6 -7
package/package.json
CHANGED
|
@@ -53,7 +53,24 @@ const ItemQuickAction = memo(({ sensor, wrapperStyle, setStatus }) => {
|
|
|
53
53
|
}, [sensor, configValues, statusCallback]);
|
|
54
54
|
const userId = useSCContextSelector((state) => state?.auth.account.user.id);
|
|
55
55
|
const onActionPress = useCallback(() => {
|
|
56
|
-
|
|
56
|
+
let data = null;
|
|
57
|
+
if (
|
|
58
|
+
action?.allow_config_store_value_id === sensor?.quick_action?.config_id
|
|
59
|
+
) {
|
|
60
|
+
if (action?.name?.toLowerCase().includes('off')) {
|
|
61
|
+
data = {
|
|
62
|
+
config_id: action?.allow_config_store_value_id,
|
|
63
|
+
config_value: 0,
|
|
64
|
+
};
|
|
65
|
+
} else {
|
|
66
|
+
data = {
|
|
67
|
+
config_id: action?.allow_config_store_value_id,
|
|
68
|
+
config_value: 1,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
data = JSON.stringify(data);
|
|
72
|
+
}
|
|
73
|
+
sendRemoteCommand(sensor, action, data, userId);
|
|
57
74
|
setIsSendingCommand(true);
|
|
58
75
|
|
|
59
76
|
if (!sensor.quick_action) {
|
|
@@ -41,10 +41,12 @@ describe('Test ItemQuickAction', () => {
|
|
|
41
41
|
|
|
42
42
|
const sensor = {
|
|
43
43
|
action: {
|
|
44
|
+
name: 'off',
|
|
44
45
|
color: '#00979D',
|
|
45
46
|
command_prefer_over_bluetooth: true,
|
|
46
47
|
command_prefer_over_googlehome: false,
|
|
47
48
|
command_prefer_over_internet: false,
|
|
49
|
+
allow_config_store_value_id: 51,
|
|
48
50
|
id: 9,
|
|
49
51
|
},
|
|
50
52
|
quick_action: {
|
|
@@ -73,6 +75,7 @@ describe('Test ItemQuickAction', () => {
|
|
|
73
75
|
command_prefer_over_bluetooth: true,
|
|
74
76
|
command_prefer_over_googlehome: false,
|
|
75
77
|
command_prefer_over_internet: false,
|
|
78
|
+
allow_config_store_value_id: 51,
|
|
76
79
|
id: 10,
|
|
77
80
|
},
|
|
78
81
|
status: 'OFF',
|
|
@@ -136,7 +139,7 @@ describe('Test ItemQuickAction', () => {
|
|
|
136
139
|
expect(mockSetState).toBeCalledWith(sensor.quick_action.off_action);
|
|
137
140
|
});
|
|
138
141
|
|
|
139
|
-
test('render with icon_outlined poweroff', () => {
|
|
142
|
+
test('render with icon_outlined poweroff and action have allow_config_store_value_id', () => {
|
|
140
143
|
const mockSetStatus = jest.fn();
|
|
141
144
|
sensor.action.icon = null;
|
|
142
145
|
act(() => {
|
|
@@ -162,7 +165,12 @@ describe('Test ItemQuickAction', () => {
|
|
|
162
165
|
act(() => {
|
|
163
166
|
buttonOnActionPress.props.onPress();
|
|
164
167
|
});
|
|
165
|
-
expect(mockSendRemoteControl).
|
|
168
|
+
expect(mockSendRemoteControl).toBeCalledWith(
|
|
169
|
+
sensor,
|
|
170
|
+
sensor.action,
|
|
171
|
+
JSON.stringify({ config_id: 51, config_value: 0 }),
|
|
172
|
+
undefined
|
|
173
|
+
);
|
|
166
174
|
expect(mockSetState).toBeCalledTimes(1);
|
|
167
175
|
|
|
168
176
|
jest.runAllTimers();
|
|
@@ -249,10 +257,12 @@ describe('Test ItemQuickAction', () => {
|
|
|
249
257
|
test('trigger action with quick action no auto update', () => {
|
|
250
258
|
const noAutoUpdateSensor = {
|
|
251
259
|
action: {
|
|
260
|
+
name: 'on',
|
|
252
261
|
color: '#00979D',
|
|
253
262
|
command_prefer_over_bluetooth: true,
|
|
254
263
|
command_prefer_over_googlehome: false,
|
|
255
264
|
command_prefer_over_internet: false,
|
|
265
|
+
allow_config_store_value_id: 51,
|
|
256
266
|
id: 9,
|
|
257
267
|
icon: 'caret-up',
|
|
258
268
|
},
|
|
@@ -297,6 +307,12 @@ describe('Test ItemQuickAction', () => {
|
|
|
297
307
|
act(() => {
|
|
298
308
|
buttonOnActionPress.props.onPress();
|
|
299
309
|
});
|
|
310
|
+
expect(mockSendRemoteControl).toBeCalledWith(
|
|
311
|
+
noAutoUpdateSensor,
|
|
312
|
+
noAutoUpdateSensor.action,
|
|
313
|
+
JSON.stringify({ config_id: 51, config_value: 1 }),
|
|
314
|
+
undefined
|
|
315
|
+
);
|
|
300
316
|
expect(mockSetState).toBeCalledTimes(1);
|
|
301
317
|
|
|
302
318
|
jest.runAllTimers();
|
|
@@ -29,16 +29,19 @@ const NumberUpDownActionTemplate = ({
|
|
|
29
29
|
// eslint-disable-next-line no-unused-vars
|
|
30
30
|
const [configValues, setConfigValues] = useConfigGlobalState('configValues');
|
|
31
31
|
const valueDefault = 28;
|
|
32
|
-
const [value, setValue] = useState(
|
|
32
|
+
const [value, setValue] = useState();
|
|
33
33
|
|
|
34
34
|
useEffect(() => {
|
|
35
35
|
if (!config) {
|
|
36
|
+
setValue(valueDefault);
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
const configValue = configValues[config];
|
|
40
41
|
if (configValue?.value !== null && configValue?.value !== undefined) {
|
|
41
42
|
setValue(configValue.value);
|
|
43
|
+
} else {
|
|
44
|
+
setValue(valueDefault);
|
|
42
45
|
}
|
|
43
46
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
44
47
|
}, [JSON.stringify(configValues)]);
|
|
@@ -50,7 +53,7 @@ const NumberUpDownActionTemplate = ({
|
|
|
50
53
|
data = { temperature: actionValue };
|
|
51
54
|
if (allow_config_store_value && config) {
|
|
52
55
|
data.config_id = config;
|
|
53
|
-
data.
|
|
56
|
+
data.config_value = actionValue;
|
|
54
57
|
}
|
|
55
58
|
data = JSON.stringify(data);
|
|
56
59
|
}
|
|
@@ -22,19 +22,25 @@ const getComponent = (template) => {
|
|
|
22
22
|
|
|
23
23
|
const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
24
24
|
const { configuration = {} } = actionGroup;
|
|
25
|
-
const {
|
|
25
|
+
const {
|
|
26
|
+
action_data,
|
|
27
|
+
action_on_data,
|
|
28
|
+
action_off_data,
|
|
29
|
+
is_on_value,
|
|
30
|
+
config,
|
|
31
|
+
allow_config_store_value,
|
|
32
|
+
} = configuration;
|
|
26
33
|
|
|
27
34
|
// eslint-disable-next-line no-unused-vars
|
|
28
35
|
const [configValues, _] = useConfigGlobalState('configValues');
|
|
29
36
|
|
|
30
37
|
const getIsOnValue = useCallback(() => {
|
|
31
|
-
const { is_on_value, config } = configuration;
|
|
32
38
|
const configValue = configValues[config];
|
|
33
39
|
if (is_on_value && is_on_value.length > 0) {
|
|
34
40
|
return is_on_value.includes(configValue?.value);
|
|
35
41
|
}
|
|
36
42
|
return !!configValue?.value;
|
|
37
|
-
}, [configValues,
|
|
43
|
+
}, [config, configValues, is_on_value]);
|
|
38
44
|
|
|
39
45
|
const [isOn, setIsOn] = useState(false);
|
|
40
46
|
const [tempIsOn, setTempIsOn] = useState(getIsOnValue());
|
|
@@ -49,10 +55,21 @@ const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
49
55
|
switch (sensor?.device_type) {
|
|
50
56
|
case DEVICE_TYPE.ZIGBEE:
|
|
51
57
|
if (action_on_data && action_off_data) {
|
|
58
|
+
let data;
|
|
52
59
|
if (isOn) {
|
|
53
|
-
|
|
60
|
+
data = { state: 0 };
|
|
61
|
+
if (allow_config_store_value && config) {
|
|
62
|
+
data.config_id = config;
|
|
63
|
+
data.config_value = 0;
|
|
64
|
+
}
|
|
65
|
+
await doAction(action_off_data, JSON.stringify(data));
|
|
54
66
|
} else {
|
|
55
|
-
|
|
67
|
+
data = { state: 1 };
|
|
68
|
+
if (allow_config_store_value && config) {
|
|
69
|
+
data.config_id = config;
|
|
70
|
+
data.config_value = 1;
|
|
71
|
+
}
|
|
72
|
+
await doAction(action_on_data, JSON.stringify(data));
|
|
56
73
|
}
|
|
57
74
|
}
|
|
58
75
|
break;
|
|
@@ -81,22 +98,23 @@ const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
81
98
|
}
|
|
82
99
|
updateStatusFromPusher();
|
|
83
100
|
if (sensor?.is_managed_by_backend) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
101
|
+
if (config && sensor.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
102
|
+
watchMultiConfigs([config]);
|
|
103
|
+
}
|
|
87
104
|
}
|
|
88
105
|
}, [
|
|
106
|
+
allow_config_store_value,
|
|
107
|
+
config,
|
|
89
108
|
action_data,
|
|
90
109
|
action_off_data,
|
|
91
110
|
action_on_data,
|
|
92
|
-
configuration?.config,
|
|
93
111
|
doAction,
|
|
94
112
|
isOn,
|
|
95
113
|
sensor?.device_type,
|
|
96
114
|
sensor?.is_managed_by_backend,
|
|
97
115
|
]);
|
|
98
116
|
|
|
99
|
-
useUnwatchLGDeviceConfigControl(sensor, [
|
|
117
|
+
useUnwatchLGDeviceConfigControl(sensor, [config]);
|
|
100
118
|
|
|
101
119
|
useEffect(() => {
|
|
102
120
|
setIsOn(getIsOnValue());
|
|
@@ -17,8 +17,8 @@ import SvgDoorState from '../../../assets/images/Device/door-state.svg';
|
|
|
17
17
|
import SvgCurrentState from '../../../assets/images/Device/current-state.svg';
|
|
18
18
|
import SvgWindStrength from '../../../assets/images/Device/wind-strength.svg';
|
|
19
19
|
|
|
20
|
-
function getOptionValue(option) {
|
|
21
|
-
if (option.value_text) {
|
|
20
|
+
function getOptionValue(option, allow_config_store_value) {
|
|
21
|
+
if (option.value_text && !allow_config_store_value) {
|
|
22
22
|
return option.value_text;
|
|
23
23
|
}
|
|
24
24
|
return option.value_int;
|
|
@@ -38,6 +38,7 @@ const OptionsDropdownActionTemplate = ({
|
|
|
38
38
|
icon,
|
|
39
39
|
icon_outlined,
|
|
40
40
|
config,
|
|
41
|
+
allow_config_store_value,
|
|
41
42
|
} = configuration;
|
|
42
43
|
// eslint-disable-next-line no-unused-vars
|
|
43
44
|
const [configValues, setConfigValues] = useConfigGlobalState('configValues');
|
|
@@ -50,13 +51,13 @@ const OptionsDropdownActionTemplate = ({
|
|
|
50
51
|
|
|
51
52
|
for (let i = 0; i < options.length; i++) {
|
|
52
53
|
const option = options[i];
|
|
53
|
-
const value = getOptionValue(option);
|
|
54
|
+
const value = getOptionValue(option, allow_config_store_value);
|
|
54
55
|
if (value === currentValue) {
|
|
55
56
|
return option;
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
return options[0];
|
|
59
|
-
}, [configValues, config, options]);
|
|
60
|
+
}, [configValues, config, options, allow_config_store_value]);
|
|
60
61
|
|
|
61
62
|
const { stateAlert, hideAlertAction, onShowAlert } = useDropdownAction();
|
|
62
63
|
const [selectedIndex, setSelectedIndex] = useState(
|
|
@@ -69,13 +70,18 @@ const OptionsDropdownActionTemplate = ({
|
|
|
69
70
|
|
|
70
71
|
const onDone = useCallback(() => {
|
|
71
72
|
const newOption = options[selectedIndex];
|
|
72
|
-
const value = getOptionValue(newOption);
|
|
73
|
+
const value = getOptionValue(newOption, allow_config_store_value);
|
|
74
|
+
|
|
75
|
+
let data = { level: value, key_code: newOption?.value_int };
|
|
76
|
+
if (allow_config_store_value && config) {
|
|
77
|
+
data.config_id = config;
|
|
78
|
+
data.config_value = newOption?.value_int;
|
|
79
|
+
}
|
|
80
|
+
data = JSON.stringify(data);
|
|
73
81
|
|
|
74
|
-
let data = JSON.stringify({ level: value, key_code: newOption?.value_int });
|
|
75
82
|
if (sensor.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
76
83
|
data = value;
|
|
77
84
|
}
|
|
78
|
-
|
|
79
85
|
doAction(action_data, data);
|
|
80
86
|
if (sensor?.is_managed_by_backend) {
|
|
81
87
|
config &&
|
|
@@ -84,8 +90,9 @@ const OptionsDropdownActionTemplate = ({
|
|
|
84
90
|
}
|
|
85
91
|
hideAlertAction();
|
|
86
92
|
}, [
|
|
87
|
-
action_data,
|
|
88
93
|
config,
|
|
94
|
+
allow_config_store_value,
|
|
95
|
+
action_data,
|
|
89
96
|
doAction,
|
|
90
97
|
hideAlertAction,
|
|
91
98
|
options,
|
|
@@ -34,20 +34,34 @@ const GridItem = ({ item, index, length, doAction, sensor, title }) => {
|
|
|
34
34
|
icon_outlined,
|
|
35
35
|
action_data,
|
|
36
36
|
config,
|
|
37
|
+
is_on_value,
|
|
38
|
+
allow_config_store_value,
|
|
37
39
|
} = item;
|
|
38
40
|
const buttonOnOffStyle = active ? buttonStyle.ON : buttonStyle.OFF;
|
|
39
41
|
const checkIcon = /\d/.test(icon); // to do check icon svg and icon antDesign
|
|
40
|
-
|
|
41
42
|
const doActionAndWatchConfig = useCallback(
|
|
42
43
|
(actionData) => {
|
|
43
|
-
|
|
44
|
+
let data = {};
|
|
45
|
+
if (allow_config_store_value && config) {
|
|
46
|
+
data = JSON.stringify({ config_id: config, config_value: is_on_value });
|
|
47
|
+
} else {
|
|
48
|
+
data = null;
|
|
49
|
+
}
|
|
50
|
+
doAction(actionData, data);
|
|
44
51
|
if (sensor?.is_managed_by_backend) {
|
|
45
|
-
config &&
|
|
46
|
-
sensor.device_type === DEVICE_TYPE.LG_THINQ &&
|
|
52
|
+
if (config && sensor.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
47
53
|
watchMultiConfigs([config]);
|
|
54
|
+
}
|
|
48
55
|
}
|
|
49
56
|
},
|
|
50
|
-
[
|
|
57
|
+
[
|
|
58
|
+
allow_config_store_value,
|
|
59
|
+
config,
|
|
60
|
+
doAction,
|
|
61
|
+
sensor?.is_managed_by_backend,
|
|
62
|
+
sensor.device_type,
|
|
63
|
+
is_on_value,
|
|
64
|
+
]
|
|
51
65
|
);
|
|
52
66
|
|
|
53
67
|
useUnwatchLGDeviceConfigControl(sensor, [config]);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React, { memo, useCallback } from 'react';
|
|
2
2
|
import { TouchableOpacity } from 'react-native';
|
|
3
|
+
import AccessibilityLabel from '../../configs/AccessibilityLabel';
|
|
3
4
|
import Text from '../Text';
|
|
4
5
|
import styles from './OnOffButtonActionStyles';
|
|
5
6
|
|
|
6
|
-
const OnOffButtonAction = ({ configuration, onPress, template }) => {
|
|
7
|
+
const OnOffButtonAction = ({ title, configuration, onPress, template }) => {
|
|
7
8
|
const { text_on, text_off, action_on, action_off } = configuration;
|
|
8
9
|
const onPressActionOn = useCallback(() => {
|
|
9
10
|
onPress &&
|
|
@@ -26,13 +27,21 @@ const OnOffButtonAction = ({ configuration, onPress, template }) => {
|
|
|
26
27
|
return (
|
|
27
28
|
<>
|
|
28
29
|
<TouchableOpacity onPress={onPressActionOn}>
|
|
29
|
-
<Text
|
|
30
|
-
|
|
30
|
+
<Text
|
|
31
|
+
type="H4"
|
|
32
|
+
style={styles.textwithline}
|
|
33
|
+
accessibilityLabel={AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE}
|
|
34
|
+
>
|
|
35
|
+
{title} {text_on}
|
|
31
36
|
</Text>
|
|
32
37
|
</TouchableOpacity>
|
|
33
38
|
<TouchableOpacity onPress={onPressActionOff}>
|
|
34
|
-
<Text
|
|
35
|
-
|
|
39
|
+
<Text
|
|
40
|
+
type="H4"
|
|
41
|
+
style={styles.textwithline}
|
|
42
|
+
accessibilityLabel={AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE}
|
|
43
|
+
>
|
|
44
|
+
{title} {text_off}
|
|
36
45
|
</Text>
|
|
37
46
|
</TouchableOpacity>
|
|
38
47
|
</>
|
|
@@ -5,10 +5,17 @@ import { TouchableOpacity } from 'react-native';
|
|
|
5
5
|
import OnOffButtonAction from '../OnOffButtonAction';
|
|
6
6
|
import { SCProvider } from '../../../context';
|
|
7
7
|
import { mockSCStore } from '../../../context/mockStore';
|
|
8
|
+
import Text from '../../Text';
|
|
9
|
+
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
8
10
|
|
|
9
11
|
const wrapComponent = (configuration, onPress) => (
|
|
10
12
|
<SCProvider initState={mockSCStore({})}>
|
|
11
|
-
<OnOffButtonAction
|
|
13
|
+
<OnOffButtonAction
|
|
14
|
+
configuration={configuration}
|
|
15
|
+
onPress={onPress}
|
|
16
|
+
title={'Cong tac 1'}
|
|
17
|
+
template={'on_off_button_action_template'}
|
|
18
|
+
/>
|
|
12
19
|
</SCProvider>
|
|
13
20
|
);
|
|
14
21
|
|
|
@@ -16,7 +23,12 @@ describe('Test OnOffButtonAction', () => {
|
|
|
16
23
|
let tree;
|
|
17
24
|
|
|
18
25
|
test('test onPress', () => {
|
|
19
|
-
const configuration = {
|
|
26
|
+
const configuration = {
|
|
27
|
+
text_on: 'On',
|
|
28
|
+
text_off: 'Off',
|
|
29
|
+
action_off: 'f49e1577-493d-4bae-a9ab-3b0f96a4ec52',
|
|
30
|
+
action_on: '94600cbe-2035-47d5-bd43-89ace5d59796',
|
|
31
|
+
};
|
|
20
32
|
const mockFuntion = jest.fn();
|
|
21
33
|
act(() => {
|
|
22
34
|
tree = renderer.create(wrapComponent(configuration, mockFuntion));
|
|
@@ -30,5 +42,14 @@ describe('Test OnOffButtonAction', () => {
|
|
|
30
42
|
touchOpacity[1].props.onPress();
|
|
31
43
|
});
|
|
32
44
|
expect(mockFuntion).toHaveBeenCalled();
|
|
45
|
+
|
|
46
|
+
const textTitle = instance.findAll(
|
|
47
|
+
(el) =>
|
|
48
|
+
el.props.accessibilityLabel ===
|
|
49
|
+
AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE && el.type === Text
|
|
50
|
+
);
|
|
51
|
+
expect(textTitle).toHaveLength(2);
|
|
52
|
+
expect(textTitle[0].props.children).toEqual(['Cong tac 1', ' ', 'On']);
|
|
53
|
+
expect(textTitle[1].props.children).toEqual(['Cong tac 1', ' ', 'Off']);
|
|
33
54
|
});
|
|
34
55
|
});
|
|
@@ -93,12 +93,14 @@ describe('Test ActionTemplate', () => {
|
|
|
93
93
|
act(() => {
|
|
94
94
|
threeButtonAction.props.onPress({
|
|
95
95
|
name: 'OPEN',
|
|
96
|
+
action_name: 'OPEN',
|
|
96
97
|
action: '94ae262d-46e3-42ff-9d10-516831ecc830',
|
|
97
98
|
template: 'three_button_action_template',
|
|
98
99
|
});
|
|
99
100
|
});
|
|
100
101
|
expect(mockOnSelectAction).toBeCalledWith({
|
|
101
102
|
action: '94ae262d-46e3-42ff-9d10-516831ecc830',
|
|
103
|
+
action_name: 'OPEN',
|
|
102
104
|
data: null,
|
|
103
105
|
template: 'three_button_action_template',
|
|
104
106
|
});
|
|
@@ -13,6 +13,7 @@ const ItemAutomate = ({
|
|
|
13
13
|
textCondition,
|
|
14
14
|
index,
|
|
15
15
|
setSelectedIndex,
|
|
16
|
+
onPress,
|
|
16
17
|
}) => {
|
|
17
18
|
const t = useTranslations();
|
|
18
19
|
const item = AUTOMATES[type];
|
|
@@ -30,13 +31,21 @@ const ItemAutomate = ({
|
|
|
30
31
|
}, [isItemOneTap, isSelected, item?.explanation, t, textCondition]);
|
|
31
32
|
|
|
32
33
|
const handleSelectIndex = useCallback(() => {
|
|
34
|
+
if (onPress) {
|
|
35
|
+
onPress();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!setSelectedIndex) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
setSelectedIndex((currentIndex) => {
|
|
34
43
|
if (currentIndex !== index) {
|
|
35
44
|
return index;
|
|
36
45
|
}
|
|
37
46
|
return -1;
|
|
38
47
|
});
|
|
39
|
-
}, [index, setSelectedIndex]);
|
|
48
|
+
}, [index, setSelectedIndex, onPress]);
|
|
40
49
|
|
|
41
50
|
return (
|
|
42
51
|
<TouchableOpacity
|
|
@@ -28,7 +28,7 @@ const NumberUpDownActionTemplate = memo(({ data, onSelectAction }) => {
|
|
|
28
28
|
setValue(valueDefault);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
const configValue = configValues[config];
|
|
31
|
+
const configValue = configValues[config]?.value;
|
|
32
32
|
if (configValue !== null && configValue !== undefined) {
|
|
33
33
|
setValue(configValue);
|
|
34
34
|
} else {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TouchableOpacity } from 'react-native';
|
|
3
|
+
import { create, act } from 'react-test-renderer';
|
|
4
|
+
|
|
5
|
+
import { SCProvider } from '../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import Tabbar from '..';
|
|
8
|
+
|
|
9
|
+
const wrapComponent = (props) => (
|
|
10
|
+
<SCProvider initState={mockSCStore({})}>
|
|
11
|
+
<Tabbar {...props} />
|
|
12
|
+
</SCProvider>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const mockNavigate = jest.fn();
|
|
16
|
+
jest.mock('@react-navigation/native', () => {
|
|
17
|
+
return {
|
|
18
|
+
...jest.requireActual('@react-navigation/native'),
|
|
19
|
+
useRoute: jest.fn(),
|
|
20
|
+
useNavigation: () => ({
|
|
21
|
+
navigate: mockNavigate,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
jest.mock('react', () => {
|
|
27
|
+
return {
|
|
28
|
+
...jest.requireActual('react'),
|
|
29
|
+
memo: (x) => x,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('Test HanetCameraDetail', () => {
|
|
34
|
+
Date.now = jest.fn(() => new Date('2021-09-09T10:00:00.000Z'));
|
|
35
|
+
let tree, props;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
props = {
|
|
39
|
+
state: {
|
|
40
|
+
index: 100,
|
|
41
|
+
routes: [
|
|
42
|
+
{
|
|
43
|
+
key: 'key1',
|
|
44
|
+
name: 'route1',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: 'key2',
|
|
48
|
+
name: 'route2',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
key: 'key3',
|
|
52
|
+
name: 'route3',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
descriptors: {
|
|
57
|
+
key1: {
|
|
58
|
+
options: {
|
|
59
|
+
tabBarLabel: 'label',
|
|
60
|
+
title: 'title',
|
|
61
|
+
isMainSource: true,
|
|
62
|
+
tabOffSetValue: 100,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
key2: {
|
|
66
|
+
options: {
|
|
67
|
+
tabBarLabel: undefined,
|
|
68
|
+
title: 'title',
|
|
69
|
+
isMainSource: true,
|
|
70
|
+
tabOffSetValue: 100,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
key3: {
|
|
74
|
+
options: {
|
|
75
|
+
tabBarLabel: undefined,
|
|
76
|
+
title: undefined,
|
|
77
|
+
isMainSource: true,
|
|
78
|
+
tabOffSetValue: 100,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
navigation: {
|
|
83
|
+
navigate: jest.fn(),
|
|
84
|
+
emit: jest.fn(),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('Test render HanetCameraDetail', async () => {
|
|
90
|
+
await act(async () => {
|
|
91
|
+
tree = await create(wrapComponent(props));
|
|
92
|
+
});
|
|
93
|
+
const instance = tree.root;
|
|
94
|
+
const buttons = instance.findAllByType(TouchableOpacity);
|
|
95
|
+
expect(buttons).toHaveLength(3);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -520,6 +520,9 @@ export default {
|
|
|
520
520
|
NUMBER_ACTION_UP: 'NUMBER_ACTION_UP',
|
|
521
521
|
NUMBER_ACTION_DOWN: 'NUMBER_ACTION_DOWN',
|
|
522
522
|
|
|
523
|
+
// OnOffButtonAction
|
|
524
|
+
ON_OFF_BUTTON_ACTION_TITLE: 'ON_OFF_BUTTON_ACTION_TITLE',
|
|
525
|
+
|
|
523
526
|
// Add New Device LG
|
|
524
527
|
ADD_NEW_DEVICE_LG_ADD: 'ADD_NEW_DEVICE_LG_ADD',
|
|
525
528
|
ADD_NEW_DEVICE_LG_THEN_SELECT: 'ADD_NEW_DEVICE_LG_THEN_SELECT',
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
import { withRemoteControl } from '../index';
|
|
4
|
+
import { SCProvider } from '../../context';
|
|
5
|
+
import { mockSCStore } from '../../context/mockStore';
|
|
6
|
+
|
|
7
|
+
describe('Test withRemoteControl', () => {
|
|
8
|
+
let tree;
|
|
9
|
+
|
|
10
|
+
it('test send remote command action null', async () => {
|
|
11
|
+
const Component = () => <></>;
|
|
12
|
+
const WrappedComponent = withRemoteControl(Component);
|
|
13
|
+
await act(async () => {
|
|
14
|
+
tree = renderer.create(
|
|
15
|
+
<SCProvider initState={mockSCStore({})}>
|
|
16
|
+
<WrappedComponent />
|
|
17
|
+
</SCProvider>
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
const instance = tree.root;
|
|
21
|
+
const _Component = instance.findByType(Component);
|
|
22
|
+
expect(_Component.props.sendRemoteCommand).toBeDefined();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
4
|
+
import { useAndroidTranslucentStatusBar } from '../index';
|
|
5
|
+
import { SCProvider } from '../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
|
|
8
|
+
const mockedSetAction = jest.fn();
|
|
9
|
+
|
|
10
|
+
const wrapper = ({ children }) => <SCProvider>{children}</SCProvider>;
|
|
11
|
+
|
|
12
|
+
const mockUseContext = jest.fn().mockImplementation(() => ({
|
|
13
|
+
stateData: mockSCStore({}),
|
|
14
|
+
setAction: mockedSetAction,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
React.useContext = mockUseContext;
|
|
18
|
+
|
|
19
|
+
const mockAddListener = jest.fn();
|
|
20
|
+
jest.mock('@react-navigation/native', () => {
|
|
21
|
+
return {
|
|
22
|
+
...jest.requireActual('@react-navigation/native'),
|
|
23
|
+
useNavigation: () => ({
|
|
24
|
+
addListener: mockAddListener,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('test useAndroidTranslucentStatusBar', () => {
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
mockAddListener.mockClear();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('test useAndroidTranslucentStatusBar android', () => {
|
|
35
|
+
Platform.OS = 'android';
|
|
36
|
+
renderHook(
|
|
37
|
+
() => useAndroidTranslucentStatusBar({ background: '#ffffff' }),
|
|
38
|
+
{
|
|
39
|
+
wrapper,
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
expect(mockAddListener).not.toBeCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('test useAndroidTranslucentStatusBar ios', () => {
|
|
46
|
+
Platform.OS = 'ios';
|
|
47
|
+
renderHook(
|
|
48
|
+
() => useAndroidTranslucentStatusBar({ background: '#ffffff' }),
|
|
49
|
+
{
|
|
50
|
+
wrapper,
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
expect(mockAddListener).not.toBeCalled();
|
|
54
|
+
});
|
|
55
|
+
});
|