@eohjsc/react-native-smart-city 0.2.89 → 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.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/src/commons/ActionGroup/ColorPickerTemplate.js +30 -24
  3. package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +60 -12
  4. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/index.test.js +47 -0
  5. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +2 -0
  6. package/src/commons/ActionGroup/OnOffTemplate/index.js +48 -28
  7. package/src/commons/ActionGroup/SliderRangeTemplate.js +19 -5
  8. package/src/commons/ActionGroup/__test__/ColorPickerTemplate.test.js +74 -0
  9. package/src/commons/ActionGroup/__test__/OnOffSmartLock.test.js +107 -0
  10. package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +71 -0
  11. package/src/commons/ActionGroup/index.js +1 -1
  12. package/src/commons/Calendar/index.js +5 -1
  13. package/src/commons/ConnectingProcess/__test__/Connecting.test.js +4 -1
  14. package/src/commons/Device/HorizontalBarChart.js +6 -2
  15. package/src/commons/SubUnit/Favorites/index.js +4 -35
  16. package/src/commons/SubUnit/ShortDetail.js +7 -41
  17. package/src/configs/Constants.js +5 -0
  18. package/src/hooks/Common/index.js +2 -0
  19. package/src/hooks/Common/useSensorsStatus.js +52 -0
  20. package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +1 -0
  21. package/src/screens/AddNewGateway/__test__/SelectGateway.test.js +61 -0
  22. package/src/screens/Device/__test__/DetailHistoryChart.test.js +40 -0
  23. package/src/screens/Device/detail.js +46 -29
  24. package/src/screens/HanetCamera/Detail.js +20 -13
  25. package/src/screens/HanetCamera/ManageAccess.js +10 -52
  26. package/src/screens/HanetCamera/MemberInfo.js +59 -13
  27. package/src/screens/HanetCamera/__test__/ManageAccess.test.js +19 -0
  28. package/src/screens/HanetCamera/__test__/MemberInfo.test.js +57 -10
  29. package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +90 -0
  30. package/src/screens/HanetCamera/hooks/__test__/useHanetCheckinData.test.js +9 -12
  31. package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +10 -7
  32. package/src/screens/HanetCamera/styles/manageAccessStyles.js +0 -14
  33. package/src/screens/Unit/Detail.js +1 -7
  34. package/src/screens/Unit/components/MyUnitDevice/index.js +13 -10
  35. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
  36. package/src/utils/I18n/translations/en.json +1 -0
  37. package/src/utils/I18n/translations/vi.json +1 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eohjsc/react-native-smart-city",
3
3
  "title": "React Native Smart Home",
4
- "version": "0.2.89",
4
+ "version": "0.2.92",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -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 [valueComplete, setValueComplete] = useState(0);
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
- setValueComplete(color);
18
- doAction(configuration?.action_color_data, `{"value":"${color}"}`);
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
- const PreventColorPicker = useCallback(
24
- ({ style, color, onChangeComplete, props }) => {
25
- return (
26
- <ColorPicker
27
- style={style}
28
- sliderHidden={true}
29
- swatches={false}
30
- color={color}
31
- onColorChangeComplete={onChangeComplete}
32
- thumbSize={16}
33
- {...props}
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
- <PreventColorPicker
45
+ <ColorPicker
43
46
  style={styles.colorPicker}
44
- color={valueComplete}
45
- onChangeComplete={(color) => onChangeColor(color)}
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 [active, setActive] = useState(true);
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 handleClickButton = useCallback(() => {
15
- setActive(!active);
16
- }, [active]);
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 style={styles.wrapButtonSmartLock}>
26
- <TouchableOpacity onPress={handleClickButton}>
27
- {active ? (
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
- {active ? t('door_is_open') : t('door_is_close')}
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
- if (action_data) {
29
- if (isOn) {
30
- doAction(action_data, false);
31
- } else {
32
- doAction(action_data, true);
33
- }
34
- }
35
- if (action_on_data && action_off_data) {
36
- if (isOn) {
37
- let actionName = `${
38
- sensor?.name
39
- } ${actionGroup?.title?.toLowerCase()} off`;
40
- actionName = actionName.replace(/\s+/g, ' ').trim();
41
- doAction(action_off_data, null, actionName);
42
- } else {
43
- let actionName = `${
44
- sensor?.name
45
- } ${actionGroup?.title?.toLowerCase()} on`;
46
- actionName = actionName.replace(/\s+/g, ' ').trim();
47
- doAction(action_on_data, null, actionName);
48
- }
49
- }
50
- if (sensor?.is_managed_by_backend) {
51
- configuration.config && watchMultiConfigs([configuration.config]);
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
- actionGroup?.title,
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 Slider from 'react-native-slider';
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
- `{"value_brness":${value}}`
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
- <Slider
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 'OnOffButtonActionSmartLock':
26
+ case 'OnOffSmartLockActionTemplate':
27
27
  return OnOffSmartLock;
28
28
  case 'one_button_action_template': // todo refactor later with backend
29
29
  case 'OneBigButtonActionTemplate':