@eohjsc/react-native-smart-city 0.2.91 → 0.2.92
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/ActionGroup/ColorPickerTemplate.js +30 -24
- package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +60 -12
- package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/index.test.js +47 -0
- package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +2 -0
- package/src/commons/ActionGroup/OnOffTemplate/index.js +48 -28
- package/src/commons/ActionGroup/SliderRangeTemplate.js +19 -5
- package/src/commons/ActionGroup/__test__/ColorPickerTemplate.test.js +74 -0
- package/src/commons/ActionGroup/__test__/OnOffSmartLock.test.js +107 -0
- package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +71 -0
- package/src/commons/ActionGroup/index.js +1 -1
- package/src/commons/Calendar/index.js +5 -1
- package/src/commons/ConnectingProcess/__test__/Connecting.test.js +4 -1
- package/src/commons/Device/HorizontalBarChart.js +6 -2
- package/src/commons/SubUnit/Favorites/index.js +4 -35
- package/src/commons/SubUnit/ShortDetail.js +7 -41
- package/src/configs/Constants.js +5 -0
- package/src/hooks/Common/index.js +2 -0
- package/src/hooks/Common/useSensorsStatus.js +52 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +1 -0
- package/src/screens/AddNewGateway/__test__/SelectGateway.test.js +61 -0
- package/src/screens/Device/__test__/DetailHistoryChart.test.js +40 -0
- package/src/screens/HanetCamera/Detail.js +20 -13
- package/src/screens/HanetCamera/ManageAccess.js +10 -52
- package/src/screens/HanetCamera/MemberInfo.js +59 -13
- package/src/screens/HanetCamera/__test__/ManageAccess.test.js +19 -0
- package/src/screens/HanetCamera/__test__/MemberInfo.test.js +57 -10
- package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +90 -0
- package/src/screens/HanetCamera/hooks/__test__/useHanetCheckinData.test.js +9 -12
- package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +10 -7
- package/src/screens/HanetCamera/styles/manageAccessStyles.js +0 -14
- package/src/screens/Unit/Detail.js +1 -7
- package/src/screens/Unit/components/MyUnitDevice/index.js +13 -10
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
- package/src/utils/I18n/translations/en.json +1 -0
- package/src/utils/I18n/translations/vi.json +1 -0
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import React, { memo, useCallback, useState } from 'react';
|
|
1
|
+
import React, { memo, useCallback, useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import styles from './ColorPickerTemplateStyles';
|
|
4
4
|
import ColorPicker from 'react-native-wheel-color-picker';
|
|
5
|
+
import { watchMultiConfigs } from '../../iot/Monitor';
|
|
6
|
+
import { useConfigGlobalState } from '../../iot/states';
|
|
5
7
|
|
|
6
|
-
const ColorPickerTemplate = memo(({ actionGroup, doAction }) => {
|
|
8
|
+
const ColorPickerTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
7
9
|
const { configuration } = actionGroup;
|
|
8
|
-
const [
|
|
10
|
+
const [valueColorComplete, setValueColorComplete] = useState('');
|
|
9
11
|
const [isFirstColor, setIsFirstColor] = useState(false);
|
|
12
|
+
const [configValues] = useConfigGlobalState('configValues');
|
|
10
13
|
|
|
11
14
|
const onChangeColor = useCallback(
|
|
12
15
|
(color) => {
|
|
@@ -14,35 +17,38 @@ const ColorPickerTemplate = memo(({ actionGroup, doAction }) => {
|
|
|
14
17
|
setIsFirstColor(true);
|
|
15
18
|
return;
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
doAction(
|
|
21
|
+
configuration?.action_color_data,
|
|
22
|
+
JSON.stringify({ value: color })
|
|
23
|
+
);
|
|
19
24
|
},
|
|
20
25
|
[configuration?.action_color_data, doAction, isFirstColor]
|
|
21
26
|
);
|
|
27
|
+
const valueColor = useMemo(() => {
|
|
28
|
+
return valueColorComplete || '';
|
|
29
|
+
}, [valueColorComplete]);
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
},
|
|
37
|
-
[]
|
|
38
|
-
);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const { config } = configuration;
|
|
33
|
+
const configValue = configValues[config];
|
|
34
|
+
setValueColorComplete(configValue);
|
|
35
|
+
}, [configuration.config, configValues, configuration]);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (sensor?.is_managed_by_backend) {
|
|
39
|
+
watchMultiConfigs([configuration.config]);
|
|
40
|
+
}
|
|
41
|
+
}, [sensor, configuration.config]);
|
|
39
42
|
|
|
40
43
|
return (
|
|
41
44
|
<View style={styles.viewPickColor}>
|
|
42
|
-
<
|
|
45
|
+
<ColorPicker
|
|
43
46
|
style={styles.colorPicker}
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
sliderHidden={true}
|
|
48
|
+
swatches={false}
|
|
49
|
+
color={valueColor}
|
|
50
|
+
onColorChangeComplete={onChangeColor}
|
|
51
|
+
thumbSize={16}
|
|
46
52
|
/>
|
|
47
53
|
</View>
|
|
48
54
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo, useCallback, useState } from 'react';
|
|
1
|
+
import React, { memo, useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { SafeAreaView, TouchableOpacity, View } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
4
4
|
import { Section } from '../../Section';
|
|
@@ -6,14 +6,58 @@ import Text from '../../Text';
|
|
|
6
6
|
import styles from './OnOffSmartLockStyle';
|
|
7
7
|
import ButtonLock from '../../../../assets/images/Device/button-lock.svg';
|
|
8
8
|
import ButtonUnLock from '../../../../assets/images/Device/button-unlock.svg';
|
|
9
|
+
import { useConfigGlobalState } from '../../../iot/states';
|
|
10
|
+
import { watchMultiConfigs } from '../../../iot/Monitor';
|
|
11
|
+
import { TESTID } from '../../../configs/Constants';
|
|
9
12
|
|
|
10
13
|
const OnOffSmartLock = memo(({ actionGroup, doAction, sensor }) => {
|
|
11
14
|
const t = useTranslations();
|
|
12
|
-
const
|
|
15
|
+
const { configuration } = actionGroup;
|
|
16
|
+
const { action_on_data, action_off_data } = configuration;
|
|
17
|
+
const [isUnlock, setisUnlock] = useState(true);
|
|
18
|
+
const [configValues] = useConfigGlobalState('configValues');
|
|
13
19
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
const handleActionSmartLock = useCallback(() => {
|
|
21
|
+
if (action_on_data && action_off_data) {
|
|
22
|
+
if (isUnlock) {
|
|
23
|
+
let actionName = `${
|
|
24
|
+
sensor?.name
|
|
25
|
+
} ${actionGroup?.title?.toLowerCase()} lock`;
|
|
26
|
+
actionName = actionName.replace(/\s+/g, ' ').trim();
|
|
27
|
+
const dataLock = { door_lock: 0 };
|
|
28
|
+
doAction(action_on_data, JSON.stringify(dataLock), actionName);
|
|
29
|
+
} else {
|
|
30
|
+
let actionName = `${
|
|
31
|
+
sensor?.name
|
|
32
|
+
} ${actionGroup?.title?.toLowerCase()} unlock`;
|
|
33
|
+
actionName = actionName.replace(/\s+/g, ' ').trim();
|
|
34
|
+
const dataUnlock = { door_lock: 1 };
|
|
35
|
+
doAction(action_off_data, JSON.stringify(dataUnlock), actionName);
|
|
36
|
+
}
|
|
37
|
+
if (sensor?.is_managed_by_backend) {
|
|
38
|
+
configuration.config && watchMultiConfigs([configuration.config]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}, [
|
|
42
|
+
actionGroup?.title,
|
|
43
|
+
action_off_data,
|
|
44
|
+
action_on_data,
|
|
45
|
+
doAction,
|
|
46
|
+
isUnlock,
|
|
47
|
+
sensor?.name,
|
|
48
|
+
configuration,
|
|
49
|
+
sensor?.is_managed_by_backend,
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
const { is_on_value, config } = configuration;
|
|
54
|
+
const configValue = configValues[config];
|
|
55
|
+
if (is_on_value && is_on_value.length) {
|
|
56
|
+
setisUnlock(is_on_value.includes(configValue));
|
|
57
|
+
} else {
|
|
58
|
+
setisUnlock(configValue);
|
|
59
|
+
}
|
|
60
|
+
}, [configValues, configuration]);
|
|
17
61
|
|
|
18
62
|
return (
|
|
19
63
|
<SafeAreaView style={styles.container}>
|
|
@@ -22,21 +66,25 @@ const OnOffSmartLock = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
22
66
|
<View style={styles.wrapController}>
|
|
23
67
|
<Text style={styles.textController}>{t('controller')}</Text>
|
|
24
68
|
</View>
|
|
25
|
-
<View
|
|
26
|
-
<TouchableOpacity
|
|
27
|
-
{
|
|
69
|
+
<View>
|
|
70
|
+
<TouchableOpacity
|
|
71
|
+
onPress={handleActionSmartLock}
|
|
72
|
+
testID={TESTID.BUTTON_ON_OFF}
|
|
73
|
+
style={styles.wrapButtonSmartLock}
|
|
74
|
+
>
|
|
75
|
+
{isUnlock ? (
|
|
28
76
|
<ButtonLock style={styles.buttonSmartLock} />
|
|
29
77
|
) : (
|
|
30
78
|
<ButtonUnLock style={styles.buttonSmartLock} />
|
|
31
79
|
)}
|
|
80
|
+
<Text style={styles.textSmartLock}>
|
|
81
|
+
{t(isUnlock ? 'lock' : 'unlock')}
|
|
82
|
+
</Text>
|
|
32
83
|
</TouchableOpacity>
|
|
33
|
-
<Text style={styles.textSmartLock}>
|
|
34
|
-
{active ? t('lock') : t('unlock')}
|
|
35
|
-
</Text>
|
|
36
84
|
</View>
|
|
37
85
|
<View style={styles.wrapStatus}>
|
|
38
86
|
<Text style={styles.textStatus}>
|
|
39
|
-
{
|
|
87
|
+
{t(isUnlock ? 'door_is_open' : 'door_is_close')}
|
|
40
88
|
</Text>
|
|
41
89
|
</View>
|
|
42
90
|
</Section>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { act, create } from 'react-test-renderer';
|
|
3
|
+
|
|
4
|
+
import { mockSCStore } from '../../../../../context/mockStore';
|
|
5
|
+
import { TESTID } from '../../../../../configs/Constants';
|
|
6
|
+
import { SCProvider } from '../../../../../context';
|
|
7
|
+
import PasscodeList from '../index';
|
|
8
|
+
import { TouchableOpacity } from 'react-native';
|
|
9
|
+
|
|
10
|
+
const mockNavigate = jest.fn();
|
|
11
|
+
jest.mock('@react-navigation/native', () => {
|
|
12
|
+
return {
|
|
13
|
+
...jest.requireActual('@react-navigation/native'),
|
|
14
|
+
useNavigation: () => ({
|
|
15
|
+
navigate: mockNavigate,
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const wrapComponent = () => (
|
|
21
|
+
<SCProvider initState={mockSCStore({})}>
|
|
22
|
+
<PasscodeList />
|
|
23
|
+
</SCProvider>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
describe('Test SetupGeneratePasscode', () => {
|
|
27
|
+
let tree;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
mockNavigate.mockClear();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('render PasscodeList', async () => {
|
|
34
|
+
await act(async () => {
|
|
35
|
+
tree = await create(wrapComponent());
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const instance = tree.root;
|
|
39
|
+
const passcode_list = instance.findAll(
|
|
40
|
+
(item) =>
|
|
41
|
+
item.props.testID === TESTID.PASSCODE_LIST &&
|
|
42
|
+
item.type === TouchableOpacity
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
expect(passcode_list).toHaveLength(3);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -9,6 +9,7 @@ import t from '../../../../hooks/Common/useTranslations';
|
|
|
9
9
|
import { Colors } from '../../../../configs';
|
|
10
10
|
import Routes from '../../../../utils/Route';
|
|
11
11
|
import styles from './PasscodeListStyles';
|
|
12
|
+
import { TESTID } from '../../../../configs/Constants';
|
|
12
13
|
|
|
13
14
|
const PasscodeList = memo(() => {
|
|
14
15
|
const navigation = useNavigation();
|
|
@@ -50,6 +51,7 @@ const PasscodeList = memo(() => {
|
|
|
50
51
|
<TouchableOpacity
|
|
51
52
|
onPress={handleClickButton(item)}
|
|
52
53
|
style={styles.buttonWrapper}
|
|
54
|
+
testID={TESTID.PASSCODE_LIST}
|
|
53
55
|
>
|
|
54
56
|
<View>
|
|
55
57
|
<Text style={styles.textCode}>{item.code}</Text>
|
|
@@ -24,48 +24,69 @@ const OnOffTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
24
24
|
// eslint-disable-next-line no-unused-vars
|
|
25
25
|
const [configValues, _] = useConfigGlobalState('configValues');
|
|
26
26
|
|
|
27
|
+
const actionName = useCallback(
|
|
28
|
+
(text) => {
|
|
29
|
+
const actionNameType = `${
|
|
30
|
+
sensor?.name
|
|
31
|
+
} ${actionGroup?.title?.toLowerCase()} ${text}`;
|
|
32
|
+
return actionNameType.replace(/\s+/g, ' ').trim();
|
|
33
|
+
},
|
|
34
|
+
[actionGroup?.title, sensor?.name]
|
|
35
|
+
);
|
|
27
36
|
const triggerAction = useCallback(() => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
37
|
+
switch (sensor?.device_type) {
|
|
38
|
+
case DEVICE_TYPE.ZIGBEE:
|
|
39
|
+
if (action_on_data && action_off_data) {
|
|
40
|
+
if (isOn) {
|
|
41
|
+
doAction(
|
|
42
|
+
action_off_data,
|
|
43
|
+
JSON.stringify({ state: 0 }),
|
|
44
|
+
actionName('off')
|
|
45
|
+
);
|
|
46
|
+
} else {
|
|
47
|
+
doAction(
|
|
48
|
+
action_on_data,
|
|
49
|
+
JSON.stringify({ state: 1 }),
|
|
50
|
+
actionName('on')
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
default:
|
|
56
|
+
if (action_data) {
|
|
57
|
+
if (isOn) {
|
|
58
|
+
doAction(action_data, false);
|
|
59
|
+
} else {
|
|
60
|
+
doAction(action_data, true);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (action_on_data && action_off_data) {
|
|
64
|
+
if (isOn) {
|
|
65
|
+
doAction(action_off_data, null, actionName('off'));
|
|
66
|
+
} else {
|
|
67
|
+
doAction(action_on_data, null, actionName('on'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (sensor?.is_managed_by_backend) {
|
|
71
|
+
configuration.config && watchMultiConfigs([configuration.config]);
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
52
74
|
}
|
|
53
75
|
}, [
|
|
54
|
-
|
|
76
|
+
actionName,
|
|
55
77
|
action_data,
|
|
56
78
|
action_off_data,
|
|
57
79
|
action_on_data,
|
|
58
80
|
configuration.config,
|
|
59
81
|
doAction,
|
|
60
82
|
isOn,
|
|
83
|
+
sensor?.device_type,
|
|
61
84
|
sensor?.is_managed_by_backend,
|
|
62
|
-
sensor?.name,
|
|
63
85
|
]);
|
|
64
86
|
|
|
65
87
|
useEffect(() => {
|
|
66
88
|
const { is_on_value, config } = configuration;
|
|
67
89
|
const configValue = configValues[config];
|
|
68
|
-
|
|
69
90
|
if (is_on_value && is_on_value.length > 0) {
|
|
70
91
|
setIsOn(is_on_value.includes(configValue));
|
|
71
92
|
return;
|
|
@@ -82,7 +103,6 @@ const OnOffTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
82
103
|
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
83
104
|
return;
|
|
84
105
|
}
|
|
85
|
-
|
|
86
106
|
if (sensor?.is_managed_by_backend) {
|
|
87
107
|
watchMultiConfigs([configuration.config]);
|
|
88
108
|
}
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
import React, { memo, useCallback, useState, useMemo } from 'react';
|
|
1
|
+
import React, { memo, useCallback, useState, useMemo, useEffect } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
4
4
|
import styles from './SliderRangeTemplateStyles';
|
|
5
5
|
import Text from '../Text';
|
|
6
6
|
import { Colors } from '../../configs';
|
|
7
7
|
import SvgBrightness from '../../../assets/images/brightness.svg';
|
|
8
|
-
import
|
|
8
|
+
import SliderRange from 'react-native-slider';
|
|
9
|
+
import { watchMultiConfigs } from '../../iot/Monitor';
|
|
10
|
+
import { useConfigGlobalState } from '../../iot/states';
|
|
9
11
|
|
|
10
|
-
const SliderRangeTemplate = memo(({ actionGroup, doAction }) => {
|
|
12
|
+
const SliderRangeTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
11
13
|
const t = useTranslations();
|
|
12
14
|
const { configuration } = actionGroup;
|
|
13
15
|
const [valueBrightness, setValueBrightness] = useState(0);
|
|
16
|
+
const [configValues] = useConfigGlobalState('configValues');
|
|
14
17
|
|
|
15
18
|
const onChangeBrightness = useCallback(
|
|
16
19
|
(value) => {
|
|
17
20
|
setValueBrightness(value);
|
|
18
21
|
doAction(
|
|
19
22
|
configuration?.action_brightness_data,
|
|
20
|
-
|
|
23
|
+
JSON.stringify({ value_brness: value })
|
|
21
24
|
);
|
|
22
25
|
},
|
|
23
26
|
[configuration?.action_brightness_data, doAction]
|
|
@@ -27,6 +30,17 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction }) => {
|
|
|
27
30
|
return valueBrightness || 0;
|
|
28
31
|
}, [valueBrightness]);
|
|
29
32
|
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const { config } = configuration;
|
|
35
|
+
const configValue = configValues[config];
|
|
36
|
+
setValueBrightness(configValue);
|
|
37
|
+
}, [configuration.config, configValues, configuration]);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (sensor?.is_managed_by_backend) {
|
|
41
|
+
watchMultiConfigs([configuration.config]);
|
|
42
|
+
}
|
|
43
|
+
}, [sensor, configuration.config]);
|
|
30
44
|
return (
|
|
31
45
|
<View style={styles.viewBrightness}>
|
|
32
46
|
<View style={styles.LeftBrightness}>
|
|
@@ -37,7 +51,7 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction }) => {
|
|
|
37
51
|
</View>
|
|
38
52
|
<View style={styles.RightBrightness}>
|
|
39
53
|
<View style={styles.slider}>
|
|
40
|
-
<
|
|
54
|
+
<SliderRange
|
|
41
55
|
value={valueBrightness}
|
|
42
56
|
onSlidingComplete={onChangeBrightness}
|
|
43
57
|
onValueChange={setValueBrightness}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { watchMultiConfigs } from '../../../iot/Monitor';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { act, create } from 'react-test-renderer';
|
|
4
|
+
import ColorPickerTemplate from '../ColorPickerTemplate';
|
|
5
|
+
import { SCProvider } from '../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import { useConfigGlobalState } from '../../../iot/states';
|
|
8
|
+
import ColorPicker from 'react-native-wheel-color-picker';
|
|
9
|
+
|
|
10
|
+
jest.mock('../../../iot/Monitor');
|
|
11
|
+
const mockDoAction = jest.fn();
|
|
12
|
+
jest.mock('../../../iot/states', () => ({
|
|
13
|
+
useConfigGlobalState: jest.fn(),
|
|
14
|
+
}));
|
|
15
|
+
const mockSetState = jest.fn();
|
|
16
|
+
jest.mock('react', () => {
|
|
17
|
+
return {
|
|
18
|
+
...jest.requireActual('react'),
|
|
19
|
+
useState: jest.fn((init) => [init, mockSetState]),
|
|
20
|
+
memo: (x) => x,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
const wrapComponent = (actionGroup, doAction, sensor) => (
|
|
24
|
+
<SCProvider initState={mockSCStore({})}>
|
|
25
|
+
<ColorPickerTemplate
|
|
26
|
+
actionGroup={actionGroup}
|
|
27
|
+
doAction={doAction}
|
|
28
|
+
sensor={sensor}
|
|
29
|
+
/>
|
|
30
|
+
</SCProvider>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
describe('Test ColorPickerTemplate', () => {
|
|
34
|
+
let wrapper;
|
|
35
|
+
let actionGroup;
|
|
36
|
+
|
|
37
|
+
const action_color_data = {
|
|
38
|
+
color: '#00979D',
|
|
39
|
+
command_prefer_over_bluetooth: false,
|
|
40
|
+
command_prefer_over_googlehome: false,
|
|
41
|
+
command_prefer_over_internet: true,
|
|
42
|
+
googlehome_actions: [],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
watchMultiConfigs.mockClear();
|
|
47
|
+
mockDoAction.mockClear();
|
|
48
|
+
actionGroup = {
|
|
49
|
+
template: 'ColorPickerTemplate',
|
|
50
|
+
configuration: {
|
|
51
|
+
config: 5,
|
|
52
|
+
action_color_data: action_color_data,
|
|
53
|
+
},
|
|
54
|
+
title: '',
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('render template ColorPickerTemplate', async () => {
|
|
59
|
+
useConfigGlobalState.mockImplementation(() => [{}, jest.fn()]);
|
|
60
|
+
const sensor = {
|
|
61
|
+
is_managed_by_backend: true,
|
|
62
|
+
name: 'Sensor',
|
|
63
|
+
};
|
|
64
|
+
await act(async () => {
|
|
65
|
+
wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
|
|
66
|
+
});
|
|
67
|
+
const instance = wrapper.root;
|
|
68
|
+
const picker = instance.findAllByType(ColorPicker);
|
|
69
|
+
expect(picker).toHaveLength(1);
|
|
70
|
+
await act(async () => {
|
|
71
|
+
await picker[0].props.onColorChangeComplete();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { TESTID } from '../../../configs/Constants';
|
|
2
|
+
import { watchMultiConfigs } from '../../../iot/Monitor';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { act, create } from 'react-test-renderer';
|
|
5
|
+
import OnOffSmartLock from '../OnOffSmartLock/OnOffSmartLock';
|
|
6
|
+
import { SCProvider } from '../../../context';
|
|
7
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
8
|
+
import { useConfigGlobalState } from '../../../iot/states';
|
|
9
|
+
|
|
10
|
+
jest.mock('../../../iot/Monitor');
|
|
11
|
+
const mockDoAction = jest.fn();
|
|
12
|
+
jest.mock('../../../iot/states', () => ({
|
|
13
|
+
useConfigGlobalState: jest.fn(),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
const wrapComponent = (actionGroup, doAction, sensor) => (
|
|
17
|
+
<SCProvider initState={mockSCStore({})}>
|
|
18
|
+
<OnOffSmartLock
|
|
19
|
+
actionGroup={actionGroup}
|
|
20
|
+
doAction={doAction}
|
|
21
|
+
sensor={sensor}
|
|
22
|
+
/>
|
|
23
|
+
</SCProvider>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
describe('Test OnOffTemplate', () => {
|
|
27
|
+
let wrapper;
|
|
28
|
+
let actionGroup;
|
|
29
|
+
|
|
30
|
+
const action_on_data = {
|
|
31
|
+
color: '#00979D',
|
|
32
|
+
command_prefer_over_bluetooth: true,
|
|
33
|
+
command_prefer_over_googlehome: false,
|
|
34
|
+
command_prefer_over_internet: false,
|
|
35
|
+
googlehome_actions: [],
|
|
36
|
+
icon: 'caret-up',
|
|
37
|
+
id: 20,
|
|
38
|
+
key: 'key-2',
|
|
39
|
+
};
|
|
40
|
+
const action_off_data = {
|
|
41
|
+
color: '#00979D',
|
|
42
|
+
command_prefer_over_bluetooth: true,
|
|
43
|
+
command_prefer_over_googlehome: false,
|
|
44
|
+
command_prefer_over_internet: false,
|
|
45
|
+
googlehome_actions: [],
|
|
46
|
+
icon: 'caret-up',
|
|
47
|
+
id: 20,
|
|
48
|
+
key: 'key-3',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
watchMultiConfigs.mockClear();
|
|
53
|
+
mockDoAction.mockClear();
|
|
54
|
+
actionGroup = {
|
|
55
|
+
template: 'OnOffSmartLockActionTemplate',
|
|
56
|
+
configuration: {
|
|
57
|
+
config: 5,
|
|
58
|
+
action_on_data: action_on_data,
|
|
59
|
+
action_off_data: action_off_data,
|
|
60
|
+
icon: 'up',
|
|
61
|
+
is_on_value: '2',
|
|
62
|
+
},
|
|
63
|
+
title: 'smartlock',
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('render with template OnOffSmartLockActionTemplate doAction lock', async () => {
|
|
68
|
+
useConfigGlobalState.mockImplementation(() => [{ 5: 2 }, jest.fn()]);
|
|
69
|
+
const sensor = { is_managed_by_backend: true, name: 'Sensor' };
|
|
70
|
+
await act(async () => {
|
|
71
|
+
wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
|
|
72
|
+
});
|
|
73
|
+
const instance = wrapper.root;
|
|
74
|
+
const button = instance.find(
|
|
75
|
+
(el) => el.props.testID === TESTID.BUTTON_ON_OFF
|
|
76
|
+
);
|
|
77
|
+
await act(async () => {
|
|
78
|
+
await button.props.onPress();
|
|
79
|
+
});
|
|
80
|
+
expect(mockDoAction).toBeCalledWith(
|
|
81
|
+
action_on_data,
|
|
82
|
+
'{"door_lock":0}',
|
|
83
|
+
'Sensor smartlock lock'
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('render with template OnOffSmartLockActionTemplate doAction unlock', async () => {
|
|
88
|
+
actionGroup.configuration.is_on_value = null;
|
|
89
|
+
const sensor = { is_managed_by_backend: false, name: 'Sensor' };
|
|
90
|
+
useConfigGlobalState.mockImplementation(() => [{ 5: 0 }, jest.fn()]);
|
|
91
|
+
await act(async () => {
|
|
92
|
+
wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
|
|
93
|
+
});
|
|
94
|
+
const instance = wrapper.root;
|
|
95
|
+
const button = instance.find(
|
|
96
|
+
(el) => el.props.testID === TESTID.BUTTON_ON_OFF
|
|
97
|
+
);
|
|
98
|
+
await act(async () => {
|
|
99
|
+
await button.props.onPress();
|
|
100
|
+
});
|
|
101
|
+
expect(mockDoAction).toBeCalledWith(
|
|
102
|
+
action_off_data,
|
|
103
|
+
'{"door_lock":1}',
|
|
104
|
+
'Sensor smartlock unlock'
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { watchMultiConfigs } from '../../../iot/Monitor';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { act, create } from 'react-test-renderer';
|
|
4
|
+
import SliderRangeTemplate from '../SliderRangeTemplate';
|
|
5
|
+
import { SCProvider } from '../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import { useConfigGlobalState } from '../../../iot/states';
|
|
8
|
+
import SliderRange from 'react-native-slider';
|
|
9
|
+
|
|
10
|
+
jest.mock('../../../iot/Monitor');
|
|
11
|
+
const mockDoAction = jest.fn();
|
|
12
|
+
jest.mock('../../../iot/states', () => ({
|
|
13
|
+
useConfigGlobalState: jest.fn(),
|
|
14
|
+
}));
|
|
15
|
+
const mockSetState = jest.fn();
|
|
16
|
+
jest.mock('react', () => {
|
|
17
|
+
return {
|
|
18
|
+
...jest.requireActual('react'),
|
|
19
|
+
useState: jest.fn((init) => [init, mockSetState]),
|
|
20
|
+
memo: (x) => x,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
const wrapComponent = (actionGroup, doAction, sensor) => (
|
|
24
|
+
<SCProvider initState={mockSCStore({})}>
|
|
25
|
+
<SliderRangeTemplate
|
|
26
|
+
actionGroup={actionGroup}
|
|
27
|
+
doAction={doAction}
|
|
28
|
+
sensor={sensor}
|
|
29
|
+
/>
|
|
30
|
+
</SCProvider>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
describe('Test SliderRangeTemplate', () => {
|
|
34
|
+
let wrapper;
|
|
35
|
+
let actionGroup;
|
|
36
|
+
|
|
37
|
+
const action_brightness_data = {
|
|
38
|
+
color: '#00979D',
|
|
39
|
+
command_prefer_over_bluetooth: false,
|
|
40
|
+
command_prefer_over_googlehome: false,
|
|
41
|
+
command_prefer_over_internet: true,
|
|
42
|
+
googlehome_actions: [],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
watchMultiConfigs.mockClear();
|
|
47
|
+
mockDoAction.mockClear();
|
|
48
|
+
actionGroup = {
|
|
49
|
+
template: 'ColorPickerTemplate',
|
|
50
|
+
configuration: {
|
|
51
|
+
config: 5,
|
|
52
|
+
action_brightness_data: action_brightness_data,
|
|
53
|
+
},
|
|
54
|
+
title: '',
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('render template SliderRangeTemplate', async () => {
|
|
59
|
+
useConfigGlobalState.mockImplementation(() => [{}, jest.fn()]);
|
|
60
|
+
const sensor = { is_managed_by_backend: true, name: 'Sensor' };
|
|
61
|
+
await act(async () => {
|
|
62
|
+
wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
|
|
63
|
+
});
|
|
64
|
+
const instance = wrapper.root;
|
|
65
|
+
const silderRange = instance.findAllByType(SliderRange);
|
|
66
|
+
expect(silderRange).toHaveLength(1);
|
|
67
|
+
await act(async () => {
|
|
68
|
+
await silderRange[0].props.onSlidingComplete();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -23,7 +23,7 @@ export const getActionComponent = (template) => {
|
|
|
23
23
|
case 'OnOffButtonActionTemplate':
|
|
24
24
|
case 'OnOffSimpleActionTemplate':
|
|
25
25
|
return OnOffTemplate;
|
|
26
|
-
case '
|
|
26
|
+
case 'OnOffSmartLockActionTemplate':
|
|
27
27
|
return OnOffSmartLock;
|
|
28
28
|
case 'one_button_action_template': // todo refactor later with backend
|
|
29
29
|
case 'OneBigButtonActionTemplate':
|