@eohjsc/react-native-smart-city 0.7.8 → 0.7.10

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 (85) hide show
  1. package/assets/images/AddNewDevice/add-scan-device-icon.svg +13 -0
  2. package/assets/images/Email.svg +9 -0
  3. package/assets/images/lan.svg +3 -0
  4. package/assets/images/wifi-open.svg +3 -0
  5. package/package.json +2 -1
  6. package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
  7. package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +7 -3
  8. package/src/commons/AlertAction/index.js +1 -0
  9. package/src/commons/Auth/AccountItem.js +17 -3
  10. package/src/commons/Auth/AccountList.js +3 -7
  11. package/src/commons/ConnectWifi/__test__/ConnectWifi.test.js +373 -0
  12. package/src/commons/ConnectWifi/index.js +201 -0
  13. package/src/commons/ConnectWifi/styles.js +69 -0
  14. package/src/commons/Form/TextInputPassword.js +1 -1
  15. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
  16. package/src/configs/API.js +12 -0
  17. package/src/configs/AccessibilityLabel.js +7 -0
  18. package/src/configs/Constants.js +1 -0
  19. package/src/hooks/Common/index.js +2 -2
  20. package/src/hooks/Common/useBlockBack.js +36 -0
  21. package/src/hooks/useMqtt.js +10 -5
  22. package/src/navigations/AddGatewayStack.js +2 -0
  23. package/src/navigations/AllGatewayStack.js +4 -0
  24. package/src/navigations/Main.js +2 -2
  25. package/src/navigations/UnitStack.js +32 -0
  26. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
  27. package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
  28. package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
  29. package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
  30. package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
  31. package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
  32. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
  33. package/src/screens/AddNewGateway/configs/API.js +8 -0
  34. package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
  35. package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
  36. package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
  37. package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
  38. package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
  39. package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
  40. package/src/screens/AllGateway/Successfully/index.js +66 -0
  41. package/src/screens/AllGateway/Successfully/styles.js +35 -0
  42. package/src/screens/AllGateway/components/Information/index.js +17 -1
  43. package/src/screens/AllGateway/components/RowItem/index.js +12 -1
  44. package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
  45. package/src/screens/AllGateway/hooks/useGateway.js +13 -0
  46. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
  47. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +83 -0
  48. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
  49. package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
  50. package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
  51. package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
  52. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
  53. package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
  54. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
  55. package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
  56. package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
  57. package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
  58. package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
  59. package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
  60. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
  61. package/src/screens/Automate/EditActionsList/index.js +59 -2
  62. package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
  63. package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
  64. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
  65. package/src/screens/Automate/ScriptDetail/index.js +57 -14
  66. package/src/screens/SharedUnit/index.js +2 -2
  67. package/src/screens/Sharing/SelectUser.js +47 -47
  68. package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
  69. package/src/screens/SubUnit/ManageSubUnit.js +94 -90
  70. package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
  71. package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
  72. package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
  73. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
  74. package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
  75. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
  76. package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
  77. package/src/screens/Unit/Detail.js +2 -6
  78. package/src/screens/Unit/ManageUnit.js +1 -1
  79. package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
  80. package/src/utils/I18n/translations/en.js +46 -8
  81. package/src/utils/I18n/translations/vi.js +37 -4
  82. package/src/utils/Route/index.js +7 -0
  83. package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
  84. package/src/hooks/Common/useBlockBackAndroid.js +0 -21
  85. package/src/screens/SubUnit/DetailStyles.js +0 -46
@@ -120,4 +120,22 @@ describe('Test useGateway', () => {
120
120
  });
121
121
  expect(hook.result.current.detailDeviceZigbee).toEqual({});
122
122
  });
123
+
124
+ it('test fetchChipQrDetail', async () => {
125
+ const response = {
126
+ org_slug: 'eoh',
127
+ secret: '123456',
128
+ prefix: 'lite',
129
+ host: 'example.com',
130
+ port: 1883,
131
+ };
132
+ mock
133
+ .onGet(API.DEV_MODE.CHIP_QR_CODE.DETAIL_BY_SECRET())
134
+ .reply(200, response);
135
+
136
+ await act(async () => {
137
+ await hook.result.current.fetchChipQrDetail('123456');
138
+ });
139
+ expect(hook.result.current.detailChipQr).toEqual(response);
140
+ });
123
141
  });
@@ -19,6 +19,7 @@ export const useGateway = () => {
19
19
  const [detailDeviceZigbee, setDetailDeviceZigbee] = useState({});
20
20
  const [detailDeviceModbus, setDetailDeviceModbus] = useState({});
21
21
  const [detailDeviceInternal, setDetailDeviceInternal] = useState({});
22
+ const [detailChipQr, setDetailChipQr] = useState({});
22
23
  const [dataModalPopupCT, setDataModalPopupCT] = useState({});
23
24
  const [pages, setPages] = useState(1);
24
25
  const [loadingMore, setLoadingMore] = useState(false);
@@ -251,6 +252,16 @@ export const useGateway = () => {
251
252
  [canLoadMore]
252
253
  );
253
254
 
255
+ const fetchChipQrDetail = useCallback(async (secret) => {
256
+ const { success, data } = await axiosGet(
257
+ API.DEV_MODE.CHIP_QR_CODE.DETAIL_BY_SECRET(),
258
+ {
259
+ params: { secret },
260
+ }
261
+ );
262
+ success && setDetailChipQr(data);
263
+ }, []);
264
+
254
265
  return {
255
266
  gateways,
256
267
  fetchDataGateways,
@@ -267,11 +278,13 @@ export const useGateway = () => {
267
278
  fetchActionConfigDevice,
268
279
  fetchRegistersModbus,
269
280
  fetchActionsModbus,
281
+ fetchChipQrDetail,
270
282
  gatewayDevices,
271
283
  setSelectedIndex,
272
284
  selectedIndex,
273
285
  detailDeviceZigbee,
274
286
  detailDeviceModbus,
287
+ detailChipQr,
275
288
  setIsShowModalPopupCT,
276
289
  isShowModalPopupCT,
277
290
  setDataModalPopupCT,
@@ -81,7 +81,7 @@ const SetupConfigCondition = () => {
81
81
 
82
82
  const setupCustomCondition = () => {
83
83
  setSelectedCondition('custom');
84
- automate.value = null;
84
+ automate.value = NaN;
85
85
  setIsShowModal(true);
86
86
  };
87
87
 
@@ -98,7 +98,7 @@ const SetupConfigCondition = () => {
98
98
 
99
99
  const resetCustomizeCondition = useCallback(() => {
100
100
  automate.condition = null;
101
- automate.value = null;
101
+ automate.value = NaN;
102
102
  setCustomCondition(undefined);
103
103
  }, [automate]);
104
104
 
@@ -182,7 +182,7 @@ const SetupConfigCondition = () => {
182
182
  title={t('continue')}
183
183
  testID={'continue_button'}
184
184
  onPress={() => {
185
- if (!automate.value || !automate.condition) {
185
+ if (isNaN(automate.value) || !automate.condition) {
186
186
  ToastBottomHelper.error(t('please_enter_a_number'), '', 3000);
187
187
  return;
188
188
  }
@@ -0,0 +1,83 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import { Keyboard, TouchableWithoutFeedback, View } from 'react-native';
3
+ import { useNavigation } from '@react-navigation/native';
4
+ import styles from './Styles/SetupScriptEmailStyles';
5
+ import { HeaderCustom } from '../../../commons';
6
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
7
+
8
+ import _TextInput from '../../../commons/Form/TextInput';
9
+ import AccessibilityLabel from '../../../configs/AccessibilityLabel';
10
+ import BottomButtonView from '../../../commons/BottomButtonView';
11
+ import Routes from '../../../utils/Route';
12
+
13
+ const SetupScriptEmail = ({ route }) => {
14
+ const t = useTranslations();
15
+ const { goBack, navigate } = useNavigation();
16
+ const { automate, unitId, multiUnit } = route.params || {};
17
+ const initialUnitId = useMemo(
18
+ () => unitId || multiUnit.id,
19
+ [unitId, multiUnit?.id]
20
+ );
21
+ const [formData, setFormData] = useState({ unit: initialUnitId });
22
+
23
+ const onChangeTitle = (value) => {
24
+ setFormData((state) => ({
25
+ ...state,
26
+ title: value,
27
+ }));
28
+ };
29
+ const onChangeMessage = (value) => {
30
+ setFormData((state) => ({
31
+ ...state,
32
+ message: value,
33
+ }));
34
+ };
35
+
36
+ const onNext = useCallback(async () => {
37
+ navigate(Routes.SetupScriptReceiverEmail, {
38
+ automate,
39
+ unitId: initialUnitId,
40
+ formData,
41
+ });
42
+ }, [navigate, automate, initialUnitId, formData]);
43
+
44
+ const canSave = useMemo(() => {
45
+ const { title, message } = formData || {};
46
+ return !!title && !!message;
47
+ }, [formData]);
48
+
49
+ return (
50
+ <View style={styles.wrap}>
51
+ <HeaderCustom isShowClose onClose={goBack} title={t('email_content')} />
52
+ <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
53
+ <View style={styles.container}>
54
+ <_TextInput
55
+ placeholder={t('subject')}
56
+ onChange={onChangeTitle}
57
+ textInputStyle={styles.textTitle}
58
+ value={formData?.title}
59
+ accessibilityLabel={AccessibilityLabel.AUTOMATE_TITLE_NOTIFY}
60
+ autoFocus
61
+ />
62
+ <_TextInput
63
+ placeholder={t('message')}
64
+ onChange={onChangeMessage}
65
+ textInputStyle={styles.textMessage}
66
+ value={formData?.message}
67
+ accessibilityLabel={AccessibilityLabel.AUTOMATE_MESSAGE_NOTIFY}
68
+ multiline={true}
69
+ maxLength={255}
70
+ />
71
+ <BottomButtonView
72
+ style={styles.bottomButtonView}
73
+ mainTitle={t('next')}
74
+ onPressMain={onNext}
75
+ typeMain={canSave ? 'primary' : 'disabled'}
76
+ />
77
+ </View>
78
+ </TouchableWithoutFeedback>
79
+ </View>
80
+ );
81
+ };
82
+
83
+ export default SetupScriptEmail;
@@ -0,0 +1,166 @@
1
+ import React, { useCallback, useMemo, useState, useEffect, memo } from 'react';
2
+ import { FlatList, View } from 'react-native';
3
+ import { useNavigation } from '@react-navigation/native';
4
+ import styles from './Styles/SetupScriptReceiverEmailStyles';
5
+ import { CircleView, HeaderCustom, Text } from '../../../commons';
6
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
7
+
8
+ import BottomButtonView from '../../../commons/BottomButtonView';
9
+ import { axiosPost, axiosGet } from '../../../utils/Apis/axios';
10
+ import { API, Colors } from '../../../configs';
11
+ import { ToastBottomHelper } from '../../../utils/Utils';
12
+ import Routes from '../../../utils/Route';
13
+ import moment from 'moment';
14
+ import { Image } from 'react-native-svg';
15
+ import CheckBox from '@react-native-community/checkbox';
16
+ import { useSCContextSelector } from '../../../context';
17
+
18
+ const SetupScriptReceiverEmail = ({ route }) => {
19
+ const t = useTranslations();
20
+ const { goBack, navigate } = useNavigation();
21
+ const { automate = {}, unitId, formData } = route.params || {};
22
+ const { id: automateId } = automate;
23
+ const [members, setMembers] = useState([]);
24
+ const [listUser, setListUser] = useState([]);
25
+ const currentUserId = useSCContextSelector(
26
+ (state) => state.auth.account.user.id
27
+ );
28
+
29
+ const loadMembers = useCallback(async () => {
30
+ const { success, data } = await axiosGet(API.SHARE.UNITS_MEMBERS(unitId));
31
+ if (success) {
32
+ setMembers(data);
33
+ }
34
+ }, [unitId]);
35
+
36
+ useEffect(() => {
37
+ loadMembers();
38
+ }, [loadMembers]);
39
+
40
+ const onNext = useCallback(async () => {
41
+ formData.receiver = listUser;
42
+ const { success } = await axiosPost(
43
+ API.AUTOMATE.ADD_SCRIPT_EMAIL(automateId),
44
+ formData
45
+ );
46
+ if (success) {
47
+ ToastBottomHelper.success(t('text_done'));
48
+ navigate({
49
+ name: Routes.ScriptDetail,
50
+ merge: true,
51
+ params: { saveAt: moment().valueOf() },
52
+ });
53
+ } else {
54
+ ToastBottomHelper.error(t('error_please_try_later'));
55
+ }
56
+ }, [automateId, formData, listUser, navigate, t]);
57
+
58
+ const canSave = useMemo(() => {
59
+ const { title, message } = formData;
60
+ return !!title && !!message && !!listUser.length;
61
+ }, [formData, listUser.length]);
62
+
63
+ const arrColor = useMemo(
64
+ () => [
65
+ Colors.GeekBlue3,
66
+ Colors.Purple3,
67
+ Colors.Orange3,
68
+ Colors.Volcano3,
69
+ Colors.Blue9,
70
+ Colors.Green3,
71
+ Colors.Cyan2,
72
+ ],
73
+ []
74
+ );
75
+
76
+ const onChecked = useCallback(
77
+ (id) => (checked) => {
78
+ setListUser((prevListUser) =>
79
+ checked
80
+ ? [...prevListUser, id]
81
+ : prevListUser.filter((userId) => userId !== id)
82
+ );
83
+ },
84
+ []
85
+ );
86
+
87
+ const RowMember = memo(({ member, index, onValueChange }) => {
88
+ const { id, name, avatar, share_id, email } = member;
89
+ const [role, roleColor] = useMemo(() => {
90
+ if (!share_id) {
91
+ return [t('owner'), Colors.Primary];
92
+ }
93
+ if (id === currentUserId) {
94
+ return [t('me'), Colors.Primary];
95
+ }
96
+ return [t('member'), Colors.Gray6];
97
+ }, [share_id, id]);
98
+
99
+ const firstWordsInName = useMemo(() => {
100
+ return name.charAt();
101
+ }, [name]);
102
+
103
+ const circleColor = arrColor[index % arrColor.length];
104
+
105
+ return (
106
+ <View style={styles.rowContainer}>
107
+ <View style={styles.Border}>
108
+ <CheckBox
109
+ disabled={!email}
110
+ lineWidth={4}
111
+ value={listUser.includes(id)}
112
+ onValueChange={onValueChange(id)}
113
+ />
114
+ <View style={styles.paddingLeft16}>
115
+ {avatar ? (
116
+ <Image source={{ uri: avatar }} style={styles.avatar} />
117
+ ) : (
118
+ <CircleView size={40} backgroundColor={circleColor} center>
119
+ <Text color={Colors.White}>{firstWordsInName}</Text>
120
+ </CircleView>
121
+ )}
122
+ </View>
123
+ <View style={styles.paddingLeft16}>
124
+ <Text style={styles.titleName}>{name}</Text>
125
+ {email ? (
126
+ <Text style={styles.status}>{email}</Text>
127
+ ) : (
128
+ <Text style={styles.invalid}>{t('no_email')}</Text>
129
+ )}
130
+ </View>
131
+ <View style={styles.endFlex}>
132
+ <Text style={[styles.textRole, { color: roleColor }]}>{role}</Text>
133
+ </View>
134
+ </View>
135
+ </View>
136
+ );
137
+ });
138
+
139
+ return (
140
+ <View style={styles.wrap}>
141
+ <HeaderCustom isShowClose onClose={goBack} title={t('email_to')} />
142
+ <FlatList
143
+ data={members}
144
+ renderItem={({ item, index }) => (
145
+ <RowMember member={item} index={index} onValueChange={onChecked} />
146
+ )}
147
+ keyExtractor={(item) => item.id.toString()}
148
+ ListEmptyComponent={
149
+ <View style={styles.viewEmpty}>
150
+ <Text style={styles.textCenter}>{t('no_member')}</Text>
151
+ </View>
152
+ }
153
+ />
154
+ <View style={styles.container}>
155
+ <BottomButtonView
156
+ style={styles.bottomButtonView}
157
+ mainTitle={t('done')}
158
+ onPressMain={onNext}
159
+ typeMain={canSave ? 'primary' : 'disabled'}
160
+ />
161
+ </View>
162
+ </View>
163
+ );
164
+ };
165
+
166
+ export default SetupScriptReceiverEmail;
@@ -0,0 +1,37 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../../../configs';
3
+ import { getBottomSpace } from 'react-native-iphone-x-helper';
4
+
5
+ export default StyleSheet.create({
6
+ wrap: {
7
+ flex: 1,
8
+ backgroundColor: Colors.White,
9
+ },
10
+ container: {
11
+ flex: 1,
12
+ paddingHorizontal: 16,
13
+ paddingTop: 10,
14
+ paddingBottom: getBottomSpace() + 10,
15
+ },
16
+ textTitle: {
17
+ borderWidth: 1,
18
+ borderColor: Colors.Gray4,
19
+ borderStyle: 'solid',
20
+ borderRadius: 10,
21
+ },
22
+ textMessage: {
23
+ height: 500,
24
+ textAlignVertical: 'top',
25
+ borderWidth: 1,
26
+ borderColor: Colors.Gray4,
27
+ borderStyle: 'solid',
28
+ borderRadius: 10,
29
+ },
30
+ bottomButtonView: {
31
+ paddingTop: 24,
32
+ paddingBottom: 32,
33
+ backgroundColor: Colors.White,
34
+ borderColor: Colors.ShadownTransparent,
35
+ borderTopWidth: 1,
36
+ },
37
+ });
@@ -0,0 +1,79 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors, Constants } from '../../../../configs';
3
+ import { getBottomSpace } from 'react-native-iphone-x-helper';
4
+
5
+ export default StyleSheet.create({
6
+ wrap: {
7
+ flex: 1,
8
+ backgroundColor: Colors.White,
9
+ },
10
+ viewEmpty: {
11
+ justifyContent: 'center',
12
+ alignItems: 'center',
13
+ height: Constants.height - 200,
14
+ backgroundColor: Colors.White,
15
+ },
16
+ textCenter: {
17
+ alignSelf: 'center',
18
+ },
19
+ container: {
20
+ flex: 1,
21
+ paddingHorizontal: 16,
22
+ paddingTop: 10,
23
+ paddingBottom: getBottomSpace() + 10,
24
+ },
25
+ bottomButtonView: {
26
+ paddingTop: 24,
27
+ paddingBottom: 32,
28
+ backgroundColor: Colors.White,
29
+ borderColor: Colors.ShadownTransparent,
30
+ borderTopWidth: 1,
31
+ },
32
+ rowContainer: {
33
+ marginTop: 16,
34
+ },
35
+ textRole: {
36
+ fontSize: 12,
37
+ lineHeight: 20,
38
+ },
39
+ endFlex: {
40
+ flex: 1,
41
+ justifyContent: 'flex-start',
42
+ alignItems: 'flex-end',
43
+ },
44
+ Border: {
45
+ flexDirection: 'row',
46
+ paddingBottom: 16,
47
+ paddingHorizontal: 16,
48
+ },
49
+ titleName: {
50
+ fontSize: 16,
51
+ lineHeight: 24,
52
+ fontStyle: 'normal',
53
+ fontWeight: '400',
54
+ },
55
+ status: {
56
+ fontSize: 12,
57
+ lineHeight: 20,
58
+ fontStyle: 'normal',
59
+ fontWeight: '400',
60
+ color: Colors.Gray7,
61
+ },
62
+ invalid: {
63
+ fontSize: 12,
64
+ lineHeight: 20,
65
+ fontStyle: 'normal',
66
+ fontWeight: '400',
67
+ color: Colors.Red,
68
+ },
69
+
70
+ paddingLeft16: {
71
+ paddingLeft: 16,
72
+ },
73
+ avatar: {
74
+ height: 40,
75
+ width: 40,
76
+ borderRadius: 40,
77
+ backgroundColor: Colors.Primary,
78
+ },
79
+ });
@@ -291,7 +291,7 @@ describe('Test ChooseAction', () => {
291
291
  },
292
292
  {
293
293
  action: '800ff454-4e2a-4a38-bad6-1bded728193e',
294
- data: { config_id: config5, config_value: 1 },
294
+ data: { config_id: config5, config_value: 1, value: 1 },
295
295
  },
296
296
  ],
297
297
  })
@@ -182,7 +182,7 @@ describe('Test SetupConfigCondition', () => {
182
182
  });
183
183
  });
184
184
 
185
- it('choose config custom condition', async () => {
185
+ const testCustomCondition = async (value) => {
186
186
  useRoute.mockReturnValue({
187
187
  params: {
188
188
  automate: {},
@@ -221,7 +221,7 @@ describe('Test SetupConfigCondition', () => {
221
221
  const input = instance.findByType(TextInput);
222
222
 
223
223
  await act(async () => {
224
- input.props.onChange('123');
224
+ input.props.onChange(value.toString());
225
225
  });
226
226
 
227
227
  const bottomButtonView = instance.findByProps({
@@ -235,10 +235,18 @@ describe('Test SetupConfigCondition', () => {
235
235
  expect(global.mockedNavigate).toBeCalledWith(Routes.ValueChangeName, {
236
236
  automate: {
237
237
  condition: '<',
238
- value: 123,
238
+ value: value,
239
239
  },
240
240
  closeScreen: undefined,
241
241
  });
242
+ };
243
+
244
+ it('choose config custom condition', async () => {
245
+ await testCustomCondition(123);
246
+ });
247
+
248
+ it('test custom condition with value = 0', async () => {
249
+ await testCustomCondition(0);
242
250
  });
243
251
 
244
252
  const testConditionValue = async (value, message) => {
@@ -273,9 +281,9 @@ describe('Test SetupConfigCondition', () => {
273
281
  });
274
282
 
275
283
  if (message === null) {
276
- expect(global.mockedNavigate).toBeCalled();
284
+ expect(global.mockedNavigate).toHaveBeenCalled();
277
285
  } else {
278
- expect(spyToastError).toBeCalledWith(message, '', 3000);
286
+ expect(spyToastError).toHaveBeenCalledWith(message, '', 3000);
279
287
  }
280
288
  };
281
289
 
@@ -0,0 +1,76 @@
1
+ import { useNavigation, useRoute } from '@react-navigation/native';
2
+ import MockAdapter from 'axios-mock-adapter';
3
+ import React from 'react';
4
+ import { TouchableWithoutFeedback } from 'react-native';
5
+ import renderer, { act } from 'react-test-renderer';
6
+ import BottomButtonView from '../../../../commons/BottomButtonView';
7
+ import _TextInput from '../../../../commons/Form/TextInput';
8
+ import API from '../../../../configs/API';
9
+ import { SCProvider } from '../../../../context';
10
+ import { mockSCStore } from '../../../../context/mockStore';
11
+ import api from '../../../../utils/Apis/axios';
12
+ import Routes from '../../../../utils/Route';
13
+ import SetupScriptEmail from '../SetupScriptEmail';
14
+
15
+ const mock = new MockAdapter(api.axiosInstance);
16
+
17
+ const wrapComponent = (route) => (
18
+ <SCProvider initState={mockSCStore({})}>
19
+ <SetupScriptEmail route={route} />
20
+ </SCProvider>
21
+ );
22
+
23
+ describe('Test SetupScriptEmail', () => {
24
+ const mockedNavigate = useNavigation().navigate;
25
+
26
+ let tree;
27
+ const route = {
28
+ params: {
29
+ unitId: 1,
30
+ automateId: 1,
31
+ scriptName: 'scriptName test',
32
+ automate: {
33
+ id: 1,
34
+ sensor_id: 1,
35
+ },
36
+ closeScreen: Routes.ScriptDetail,
37
+ },
38
+ };
39
+ beforeEach(() => {
40
+ mockedNavigate.mockClear();
41
+ useRoute.mockImplementation(() => route);
42
+ });
43
+
44
+ it('SetupScriptNotify onPress create script email success', async () => {
45
+ mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(200);
46
+ await act(async () => {
47
+ tree = await renderer.create(wrapComponent(route));
48
+ });
49
+ const instance = tree.root;
50
+ const inputs = instance.findAllByType(_TextInput);
51
+ expect(inputs).toHaveLength(2);
52
+
53
+ await act(async () => {
54
+ inputs[0].props.onChange('Title');
55
+ });
56
+ const touchable = instance.findAllByType(TouchableWithoutFeedback);
57
+ await act(async () => {
58
+ touchable[0].props.onPress();
59
+ });
60
+ await act(async () => {
61
+ inputs[1].props.onChange('Message');
62
+ });
63
+ const button = instance.findByType(BottomButtonView);
64
+ await act(async () => {
65
+ button.props.onPressMain();
66
+ });
67
+ expect(mockedNavigate).toHaveBeenCalledWith(
68
+ Routes.SetupScriptReceiverEmail,
69
+ {
70
+ automate: route.params.automate,
71
+ unitId: 1,
72
+ formData: { message: 'Message', title: 'Title', unit: 1 },
73
+ }
74
+ );
75
+ });
76
+ });
@@ -0,0 +1,105 @@
1
+ import { useNavigation, useRoute } from '@react-navigation/native';
2
+ import MockAdapter from 'axios-mock-adapter';
3
+ import React from 'react';
4
+ import renderer, { act } from 'react-test-renderer';
5
+ import BottomButtonView from '../../../../commons/BottomButtonView';
6
+ import API from '../../../../configs/API';
7
+ import { SCProvider } from '../../../../context';
8
+ import { mockSCStore } from '../../../../context/mockStore';
9
+ import api from '../../../../utils/Apis/axios';
10
+ import Routes from '../../../../utils/Route';
11
+ import { ToastBottomHelper } from '../../../../utils/Utils';
12
+ import SetupScriptReceiverEmail from '../SetupScriptReceiverEmail';
13
+ import CheckBox from '@react-native-community/checkbox';
14
+
15
+ const mock = new MockAdapter(api.axiosInstance);
16
+
17
+ const wrapComponent = (route) => (
18
+ <SCProvider initState={mockSCStore({})}>
19
+ <SetupScriptReceiverEmail route={route} />
20
+ </SCProvider>
21
+ );
22
+
23
+ describe('Test SetupScriptReceiverEmail', () => {
24
+ const mockedNavigate = useNavigation().navigate;
25
+
26
+ let tree;
27
+ const route = {
28
+ params: {
29
+ unitId: 1,
30
+ automateId: 1,
31
+ automate: {
32
+ id: 1,
33
+ sensor_id: 1,
34
+ },
35
+ closeScreen: Routes.ScriptDetail,
36
+ formData: { title: 'title', message: 'message' },
37
+ },
38
+ };
39
+
40
+ const listUser = [
41
+ {
42
+ avatar: 'https://xxx',
43
+ email: 'user1.nh@eoh.io',
44
+ id: 140,
45
+ name: 'User 1',
46
+ },
47
+ {
48
+ avatar: null,
49
+ email: null,
50
+ id: 56,
51
+ name: 'User 2',
52
+ share_id: 5386,
53
+ },
54
+ ];
55
+ beforeEach(() => {
56
+ mockedNavigate.mockClear();
57
+ useRoute.mockImplementation(() => route);
58
+ });
59
+
60
+ it('SetupScriptReceiverEmail onPress create script email success', async () => {
61
+ const spyToast = jest.spyOn(ToastBottomHelper, 'success');
62
+ mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
63
+ mock.onPost(API.AUTOMATE.ADD_SCRIPT_EMAIL(1)).reply(200);
64
+ await act(async () => {
65
+ tree = await renderer.create(wrapComponent(route));
66
+ });
67
+ const instance = tree.root;
68
+ const checkboxs = instance.findAllByType(CheckBox);
69
+ expect(checkboxs).toHaveLength(2);
70
+ expect(checkboxs[0].props.disabled).toBeFalsy();
71
+ expect(checkboxs[1].props.disabled).toBeTruthy();
72
+ await act(async () => {
73
+ checkboxs[0].props.onValueChange(true);
74
+ });
75
+
76
+ const button = instance.findByType(BottomButtonView);
77
+ await act(async () => {
78
+ button.props.onPressMain();
79
+ });
80
+ expect(spyToast).toHaveBeenCalled();
81
+ });
82
+
83
+ it('SetupScriptReceiverEmail onPress create script email fail', async () => {
84
+ const spyToast = jest.spyOn(ToastBottomHelper, 'error');
85
+ mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
86
+ mock.onPost(API.AUTOMATE.ADD_SCRIPT_EMAIL(1)).reply(400);
87
+ await act(async () => {
88
+ tree = await renderer.create(wrapComponent(route));
89
+ });
90
+ const instance = tree.root;
91
+ const checkboxs = instance.findAllByType(CheckBox);
92
+ expect(checkboxs).toHaveLength(2);
93
+ expect(checkboxs[0].props.disabled).toBeFalsy();
94
+ expect(checkboxs[1].props.disabled).toBeTruthy();
95
+ await act(async () => {
96
+ checkboxs[0].props.onValueChange(true);
97
+ });
98
+
99
+ const button = instance.findByType(BottomButtonView);
100
+ await act(async () => {
101
+ button.props.onPressMain();
102
+ });
103
+ expect(spyToast).toHaveBeenCalled();
104
+ });
105
+ });