@eohjsc/react-native-smart-city 0.7.27 → 0.7.30

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 (67) hide show
  1. package/index.js +2 -0
  2. package/package.json +2 -1
  3. package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +68 -0
  4. package/src/commons/Dashboard/MyDashboardDevice/index.js +46 -11
  5. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +43 -11
  6. package/src/commons/Dashboard/MyUnit/index.js +40 -32
  7. package/src/commons/ModalAlert/index.js +51 -0
  8. package/src/commons/ModalAlert/styles.js +54 -0
  9. package/src/commons/SubUnit/ShortDetail.js +20 -4
  10. package/src/commons/SubUnit/__test__/ShortDetail.test.js +46 -1
  11. package/src/configs/API.js +6 -0
  12. package/src/configs/AccessibilityLabel.js +1 -0
  13. package/src/configs/Constants.js +7 -0
  14. package/src/configs/SCConfig.js +6 -0
  15. package/src/context/SCContext.tsx +12 -1
  16. package/src/context/SCStore.ts +14 -0
  17. package/src/context/actionType.ts +10 -0
  18. package/src/context/mockStore.ts +30 -1
  19. package/src/context/reducer.ts +35 -0
  20. package/src/hooks/IoT/useRemoteControl.js +4 -1
  21. package/src/hooks/IoT/useWatchSharedChips.js +130 -0
  22. package/src/hooks/Review/__test__/useInAppReview.test.js +99 -0
  23. package/src/hooks/Review/useInAppReview.js +70 -0
  24. package/src/hooks/useMqtt.js +78 -27
  25. package/src/iot/Monitor.js +149 -26
  26. package/src/iot/UpdateStates.js +60 -0
  27. package/src/iot/mqtt.js +177 -22
  28. package/src/navigations/UnitStack.js +16 -0
  29. package/src/screens/ActivityLog/ItemLog.js +1 -0
  30. package/src/screens/AddNewGateway/RenameNewDevices.js +5 -0
  31. package/src/screens/AddNewGateway/__test__/RenameNewDevices.test.js +18 -0
  32. package/src/screens/Automate/AddNewAction/ReceiverSelect.js +208 -0
  33. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +1 -1
  34. package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +18 -28
  35. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +22 -129
  36. package/src/screens/Automate/AddNewAction/SetupScriptReceiverNotify.js +59 -0
  37. package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +22 -129
  38. package/src/screens/Automate/AddNewAction/SetupScriptSms.js +1 -1
  39. package/src/screens/Automate/AddNewAction/Styles/{SetupScriptReceiverEmailStyles.js → ReceiverSelectStyles.js} +18 -1
  40. package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +16 -33
  41. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +10 -8
  42. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverNotify.test.js +217 -0
  43. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +10 -8
  44. package/src/screens/Automate/Components/InputName.js +5 -1
  45. package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
  46. package/src/screens/Automate/ScriptDetail/index.js +6 -6
  47. package/src/screens/CreatePassword/__test__/index.test.js +133 -0
  48. package/src/screens/CreatePassword/index.js +134 -0
  49. package/src/screens/CreatePassword/styles.js +45 -0
  50. package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +447 -0
  51. package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +344 -0
  52. package/src/screens/Device/__test__/{mqttDetail.test.js → DeviceDetail-modbus.test.js} +287 -320
  53. package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +451 -0
  54. package/src/screens/Device/__test__/DeviceDetail.test.js +502 -0
  55. package/src/screens/Device/__test__/detail.test.js +61 -3
  56. package/src/screens/Device/__test__/sensorDisplayItem.test.js +28 -3
  57. package/src/screens/Device/detail.js +14 -6
  58. package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
  59. package/src/screens/EnterPassword/__test__/EnterPassword.test.js +76 -1
  60. package/src/screens/EnterPassword/index.js +34 -4
  61. package/src/screens/EnterPassword/styles.js +1 -1
  62. package/src/utils/FactoryGateway.js +597 -0
  63. package/src/utils/I18n/translations/en.js +10 -0
  64. package/src/utils/I18n/translations/vi.js +10 -0
  65. package/src/utils/Route/index.js +3 -1
  66. package/src/utils/Validation.js +5 -0
  67. package/src/utils/store.js +5 -0
@@ -8,53 +8,43 @@ import { useTranslations } from '../../../hooks/Common/useTranslations';
8
8
  import _TextInput from '../../../commons/Form/TextInput';
9
9
  import AccessibilityLabel from '../../../configs/AccessibilityLabel';
10
10
  import BottomButtonView from '../../../commons/BottomButtonView';
11
- import { axiosPost } from '../../../utils/Apis/axios';
12
- import { API } from '../../../configs';
13
- import { ToastBottomHelper } from '../../../utils/Utils';
14
11
  import Routes from '../../../utils/Route';
15
- import moment from 'moment';
16
12
 
17
13
  const SetupScriptNotify = ({ route }) => {
18
14
  const t = useTranslations();
19
15
  const { goBack, navigate } = useNavigation();
20
- const { automate = {}, unitId, multiUnit } = route.params || {};
21
- const { id: automateId } = automate;
22
- const [notify, setNotify] = useState({ unit: unitId || multiUnit.id });
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 });
23
22
 
24
23
  const onChangeTitle = (value) => {
25
- setNotify((state) => ({
24
+ setFormData((state) => ({
26
25
  ...state,
27
26
  title: value,
28
27
  }));
29
28
  };
30
29
  const onChangeMessage = (value) => {
31
- setNotify((state) => ({
30
+ setFormData((state) => ({
32
31
  ...state,
33
32
  message: value,
34
33
  }));
35
34
  };
36
35
 
37
36
  const onNext = useCallback(async () => {
38
- const { success } = await axiosPost(
39
- API.AUTOMATE.ADD_SCRIPT_NOTIFY(automateId),
40
- notify
41
- );
42
- if (success) {
43
- ToastBottomHelper.success(t('text_done'));
44
- navigate({
45
- name: Routes.ScriptDetail,
46
- merge: true,
47
- params: { saveAt: moment().valueOf() },
48
- });
49
- } else {
50
- ToastBottomHelper.error(t('error_please_try_later'));
51
- }
52
- }, [automateId, navigate, notify, t]);
37
+ navigate(Routes.SetupScriptReceiverNotify, {
38
+ automate,
39
+ unitId: initialUnitId,
40
+ formData,
41
+ });
42
+ }, [navigate, automate, initialUnitId, formData]);
53
43
 
54
44
  const canSave = useMemo(() => {
55
- const { title, message } = notify || {};
45
+ const { title, message } = formData;
56
46
  return !!title && !!message;
57
- }, [notify]);
47
+ }, [formData]);
58
48
 
59
49
  return (
60
50
  <View style={styles.wrap}>
@@ -65,7 +55,7 @@ const SetupScriptNotify = ({ route }) => {
65
55
  placeholder={t('title_notification')}
66
56
  onChange={onChangeTitle}
67
57
  textInputStyle={styles.textTitle}
68
- value={notify?.title}
58
+ value={formData.title}
69
59
  accessibilityLabel={AccessibilityLabel.AUTOMATE_TITLE_NOTIFY}
70
60
  autoFocus
71
61
  />
@@ -73,7 +63,7 @@ const SetupScriptNotify = ({ route }) => {
73
63
  placeholder={t('message_notification')}
74
64
  onChange={onChangeMessage}
75
65
  textInputStyle={styles.textMessage}
76
- value={notify?.message}
66
+ value={formData.message}
77
67
  accessibilityLabel={AccessibilityLabel.AUTOMATE_MESSAGE_NOTIFY}
78
68
  multiline={true}
79
69
  maxLength={255}
@@ -1,41 +1,20 @@
1
- import React, { useCallback, useMemo, useState, useEffect, memo } from 'react';
2
- import { FlatList, View } from 'react-native';
1
+ import React, { useCallback, useState } from 'react';
3
2
  import { useNavigation } from '@react-navigation/native';
4
- import styles from './Styles/SetupScriptReceiverEmailStyles';
5
- import { CircleView, HeaderCustom, Text } from '../../../commons';
6
3
  import { useTranslations } from '../../../hooks/Common/useTranslations';
7
4
 
8
- import BottomButtonView from '../../../commons/BottomButtonView';
9
- import { axiosPost, axiosGet } from '../../../utils/Apis/axios';
10
- import { API, Colors } from '../../../configs';
5
+ import { axiosPost } from '../../../utils/Apis/axios';
6
+ import { API } from '../../../configs';
11
7
  import { ToastBottomHelper } from '../../../utils/Utils';
12
8
  import Routes from '../../../utils/Route';
9
+ import ReceiverSelect from './ReceiverSelect';
13
10
  import moment from 'moment';
14
- import CheckBox from '@react-native-community/checkbox';
15
- import { useSCContextSelector } from '../../../context';
16
- import { Image } from 'react-native';
17
11
 
18
12
  const SetupScriptReceiverEmail = ({ route }) => {
19
13
  const t = useTranslations();
20
- const { goBack, navigate } = useNavigation();
21
- const { automate = {}, unitId, formData } = route.params || {};
14
+ const { navigate } = useNavigation();
15
+ const { automate = {}, unitId, formData } = route.params;
22
16
  const { id: automateId } = automate;
23
- const [members, setMembers] = useState([]);
24
17
  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
18
 
40
19
  const onNext = useCallback(async () => {
41
20
  formData.receiver = listUser;
@@ -55,112 +34,26 @@ const SetupScriptReceiverEmail = ({ route }) => {
55
34
  }
56
35
  }, [automateId, formData, listUser, navigate, t]);
57
36
 
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
- );
37
+ const onLoadOption = useCallback(
38
+ (item) => {
39
+ return {
40
+ label: item.email,
41
+ invalidLabel: t('no_email'),
42
+ disabled: !item.email,
43
+ };
83
44
  },
84
- []
45
+ [t]
85
46
  );
86
47
 
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
- style={styles.checkbox}
114
- />
115
- <View style={styles.paddingLeft16}>
116
- {avatar ? (
117
- <Image source={{ uri: avatar }} style={styles.avatar} />
118
- ) : (
119
- <CircleView size={40} backgroundColor={circleColor} center>
120
- <Text color={Colors.White}>{firstWordsInName}</Text>
121
- </CircleView>
122
- )}
123
- </View>
124
- <View style={styles.paddingLeft16}>
125
- <Text style={styles.titleName}>{name}</Text>
126
- {email ? (
127
- <Text style={styles.status}>{email}</Text>
128
- ) : (
129
- <Text style={styles.invalid}>{t('no_email')}</Text>
130
- )}
131
- </View>
132
- <View style={styles.endFlex}>
133
- <Text style={[styles.textRole, { color: roleColor }]}>{role}</Text>
134
- </View>
135
- </View>
136
- </View>
137
- );
138
- });
139
-
140
48
  return (
141
- <View style={styles.wrap}>
142
- <HeaderCustom isShowClose onClose={goBack} title={t('email_to')} />
143
- <FlatList
144
- data={members}
145
- renderItem={({ item, index }) => (
146
- <RowMember member={item} index={index} onValueChange={onChecked} />
147
- )}
148
- keyExtractor={(item) => item.id.toString()}
149
- ListEmptyComponent={
150
- <View style={styles.viewEmpty}>
151
- <Text style={styles.textCenter}>{t('no_member')}</Text>
152
- </View>
153
- }
154
- />
155
- <View style={styles.container}>
156
- <BottomButtonView
157
- style={styles.bottomButtonView}
158
- mainTitle={t('done')}
159
- onPressMain={onNext}
160
- typeMain={canSave ? 'primary' : 'disabled'}
161
- />
162
- </View>
163
- </View>
49
+ <ReceiverSelect
50
+ listUser={listUser}
51
+ unitId={unitId}
52
+ title={t('notify_to')}
53
+ setListUser={setListUser}
54
+ onLoadOption={onLoadOption}
55
+ onNext={onNext}
56
+ />
164
57
  );
165
58
  };
166
59
 
@@ -0,0 +1,59 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { useNavigation } from '@react-navigation/native';
3
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
4
+
5
+ import { axiosPost } from '../../../utils/Apis/axios';
6
+ import { API } from '../../../configs';
7
+ import { ToastBottomHelper } from '../../../utils/Utils';
8
+ import Routes from '../../../utils/Route';
9
+ import ReceiverSelect from './ReceiverSelect';
10
+ import moment from 'moment';
11
+
12
+ const SetupScriptReceiverNotify = ({ route }) => {
13
+ const t = useTranslations();
14
+ const { navigate } = useNavigation();
15
+ const { automate = {}, unitId, formData } = route.params;
16
+ const { id: automateId } = automate;
17
+ const [listUser, setListUser] = useState([]);
18
+
19
+ const onNext = useCallback(async () => {
20
+ formData.receiver = listUser;
21
+ const { success } = await axiosPost(
22
+ API.AUTOMATE.ADD_SCRIPT_NOTIFY(automateId),
23
+ formData
24
+ );
25
+ if (success) {
26
+ ToastBottomHelper.success(t('text_done'));
27
+ navigate({
28
+ name: Routes.ScriptDetail,
29
+ merge: true,
30
+ params: { saveAt: moment().valueOf() },
31
+ });
32
+ } else {
33
+ ToastBottomHelper.error(t('error_please_try_later'));
34
+ }
35
+ }, [automateId, formData, listUser, navigate, t]);
36
+
37
+ const onLoadOption = useCallback(
38
+ (item) => {
39
+ return {
40
+ label: item.phone_number,
41
+ invalidLabel: t('no_phone_number'),
42
+ };
43
+ },
44
+ [t]
45
+ );
46
+
47
+ return (
48
+ <ReceiverSelect
49
+ listUser={listUser}
50
+ unitId={unitId}
51
+ title={t('notify_to')}
52
+ setListUser={setListUser}
53
+ onLoadOption={onLoadOption}
54
+ onNext={onNext}
55
+ />
56
+ );
57
+ };
58
+
59
+ export default SetupScriptReceiverNotify;
@@ -1,41 +1,20 @@
1
- import React, { useCallback, useMemo, useState, useEffect, memo } from 'react';
2
- import { FlatList, View } from 'react-native';
1
+ import React, { useCallback, useState } from 'react';
3
2
  import { useNavigation } from '@react-navigation/native';
4
- import styles from './Styles/SetupScriptReceiverEmailStyles';
5
- import { CircleView, HeaderCustom, Text } from '../../../commons';
6
3
  import { useTranslations } from '../../../hooks/Common/useTranslations';
7
4
 
8
- import BottomButtonView from '../../../commons/BottomButtonView';
9
- import { axiosPost, axiosGet } from '../../../utils/Apis/axios';
10
- import { API, Colors } from '../../../configs';
5
+ import { axiosPost } from '../../../utils/Apis/axios';
6
+ import { API } from '../../../configs';
11
7
  import { ToastBottomHelper } from '../../../utils/Utils';
12
8
  import Routes from '../../../utils/Route';
9
+ import ReceiverSelect from './ReceiverSelect';
13
10
  import moment from 'moment';
14
- import CheckBox from '@react-native-community/checkbox';
15
- import { useSCContextSelector } from '../../../context';
16
- import { Image } from 'react-native';
17
11
 
18
12
  const SetupScriptReceiverSms = ({ route }) => {
19
13
  const t = useTranslations();
20
- const { goBack, navigate } = useNavigation();
21
- const { automate = {}, unitId, formData } = route.params || {};
14
+ const { navigate } = useNavigation();
15
+ const { automate = {}, unitId, formData } = route.params;
22
16
  const { id: automateId } = automate;
23
- const [members, setMembers] = useState([]);
24
17
  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
18
 
40
19
  const onNext = useCallback(async () => {
41
20
  formData.receiver = listUser;
@@ -55,112 +34,26 @@ const SetupScriptReceiverSms = ({ route }) => {
55
34
  }
56
35
  }, [automateId, formData, listUser, navigate, t]);
57
36
 
58
- const canSave = useMemo(() => {
59
- const { message } = formData;
60
- return !!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
- );
37
+ const onLoadOption = useCallback(
38
+ (item) => {
39
+ return {
40
+ label: item.phone_number,
41
+ invalidLabel: t('no_phone_number'),
42
+ disabled: !item.phone_number,
43
+ };
83
44
  },
84
- []
45
+ [t]
85
46
  );
86
47
 
87
- const RowMember = memo(({ member, index, onValueChange }) => {
88
- const { id, name, avatar, share_id, phone_number } = 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={!phone_number}
110
- lineWidth={4}
111
- value={listUser.includes(id)}
112
- onValueChange={onValueChange(id)}
113
- style={styles.checkbox}
114
- />
115
- <View style={styles.paddingLeft16}>
116
- {avatar ? (
117
- <Image source={{ uri: avatar }} style={styles.avatar} />
118
- ) : (
119
- <CircleView size={40} backgroundColor={circleColor} center>
120
- <Text color={Colors.White}>{firstWordsInName}</Text>
121
- </CircleView>
122
- )}
123
- </View>
124
- <View style={styles.paddingLeft16}>
125
- <Text style={styles.titleName}>{name}</Text>
126
- {phone_number ? (
127
- <Text style={styles.status}>{phone_number}</Text>
128
- ) : (
129
- <Text style={styles.invalid}>{t('no_phone_number')}</Text>
130
- )}
131
- </View>
132
- <View style={styles.endFlex}>
133
- <Text style={[styles.textRole, { color: roleColor }]}>{role}</Text>
134
- </View>
135
- </View>
136
- </View>
137
- );
138
- });
139
-
140
48
  return (
141
- <View style={styles.wrap}>
142
- <HeaderCustom isShowClose onClose={goBack} title={t('sms_to')} />
143
- <FlatList
144
- data={members}
145
- renderItem={({ item, index }) => (
146
- <RowMember member={item} index={index} onValueChange={onChecked} />
147
- )}
148
- keyExtractor={(item) => item.id.toString()}
149
- ListEmptyComponent={
150
- <View style={styles.viewEmpty}>
151
- <Text style={styles.textCenter}>{t('no_member')}</Text>
152
- </View>
153
- }
154
- />
155
- <View style={styles.container}>
156
- <BottomButtonView
157
- style={styles.bottomButtonView}
158
- mainTitle={t('done')}
159
- onPressMain={onNext}
160
- typeMain={canSave ? 'primary' : 'disabled'}
161
- />
162
- </View>
163
- </View>
49
+ <ReceiverSelect
50
+ listUser={listUser}
51
+ unitId={unitId}
52
+ title={t('notify_to')}
53
+ setListUser={setListUser}
54
+ onLoadOption={onLoadOption}
55
+ onNext={onNext}
56
+ />
164
57
  );
165
58
  };
166
59
 
@@ -37,7 +37,7 @@ const SetupScriptSms = ({ route }) => {
37
37
  }, [navigate, automate, initialUnitId, formData]);
38
38
 
39
39
  const canSave = useMemo(() => {
40
- const { message } = formData || {};
40
+ const { message } = formData;
41
41
  return !!message;
42
42
  }, [formData]);
43
43
 
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet } from 'react-native';
2
- import { Colors, Constants } from '../../../../configs';
3
2
  import { getBottomSpace } from 'react-native-iphone-x-helper';
3
+ import { Colors, Constants } from '../../../../configs';
4
4
 
5
5
  export default StyleSheet.create({
6
6
  wrap: {
@@ -82,4 +82,21 @@ export default StyleSheet.create({
82
82
  width: 24,
83
83
  height: 24,
84
84
  },
85
+
86
+ wrapSelectAll: {
87
+ paddingHorizontal: 16,
88
+ paddingVertical: 8,
89
+ },
90
+ wrapCheckboxSelectAll: {
91
+ flexDirection: 'row',
92
+ alignItems: 'center',
93
+ },
94
+ checkboxSelectAll: {
95
+ marginRight: 8,
96
+ },
97
+ borderSelectAll: {
98
+ height: 1,
99
+ backgroundColor: Colors.Gray4,
100
+ marginHorizontal: 16,
101
+ },
85
102
  });
@@ -1,20 +1,14 @@
1
1
  import { useNavigation, useRoute } from '@react-navigation/native';
2
- import MockAdapter from 'axios-mock-adapter';
3
2
  import React from 'react';
4
3
  import { TouchableWithoutFeedback } from 'react-native';
5
4
  import renderer, { act } from 'react-test-renderer';
6
5
  import BottomButtonView from '../../../../commons/BottomButtonView';
7
6
  import _TextInput from '../../../../commons/Form/TextInput';
8
- import API from '../../../../configs/API';
9
7
  import { SCProvider } from '../../../../context';
10
8
  import { mockSCStore } from '../../../../context/mockStore';
11
- import api from '../../../../utils/Apis/axios';
12
9
  import Routes from '../../../../utils/Route';
13
- import { ToastBottomHelper } from '../../../../utils/Utils';
14
10
  import SetupScriptNotify from '../SetupScriptNotify';
15
11
 
16
- const mock = new MockAdapter(api.axiosInstance);
17
-
18
12
  const wrapComponent = (route) => (
19
13
  <SCProvider initState={mockSCStore({})}>
20
14
  <SetupScriptNotify route={route} />
@@ -43,8 +37,6 @@ describe('Test SetupScriptNotify', () => {
43
37
  });
44
38
 
45
39
  it('SetupScriptNotify onPress create script notify success', async () => {
46
- const spyToast = jest.spyOn(ToastBottomHelper, 'success');
47
- mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(200);
48
40
  await act(async () => {
49
41
  tree = await renderer.create(wrapComponent(route));
50
42
  });
@@ -66,14 +58,19 @@ describe('Test SetupScriptNotify', () => {
66
58
  await act(async () => {
67
59
  button.props.onPressMain();
68
60
  });
69
- expect(spyToast).toHaveBeenCalled();
61
+ expect(mockedNavigate).toHaveBeenCalledWith(
62
+ Routes.SetupScriptReceiverNotify,
63
+ {
64
+ automate: route.params.automate,
65
+ unitId: 1,
66
+ formData: { message: 'Message', title: 'Title', unit: 1 },
67
+ }
68
+ );
70
69
  });
71
70
 
72
71
  it('SetupScriptNotify onPress create script notify success with multi unit', async () => {
73
72
  route.params.unitId = null;
74
73
  route.params.multiUnit = { id: 1 };
75
- const spyToast = jest.spyOn(ToastBottomHelper, 'success');
76
- mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(200);
77
74
  await act(async () => {
78
75
  tree = await renderer.create(wrapComponent(route));
79
76
  });
@@ -95,27 +92,13 @@ describe('Test SetupScriptNotify', () => {
95
92
  await act(async () => {
96
93
  button.props.onPressMain();
97
94
  });
98
- expect(spyToast).toHaveBeenCalled();
99
- });
100
-
101
- it('SetupScriptNotify onPress create script notify error', async () => {
102
- const spyToast = jest.spyOn(ToastBottomHelper, 'error');
103
- mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(400);
104
- await act(async () => {
105
- tree = await renderer.create(wrapComponent(route));
106
- });
107
- const instance = tree.root;
108
- const inputs = instance.findAllByType(_TextInput);
109
- expect(inputs).toHaveLength(2);
110
-
111
- await act(async () => {
112
- inputs[0].props.onChange('Title');
113
- inputs[1].props.onChange('Message');
114
- });
115
- const button = instance.findByType(BottomButtonView);
116
- await act(async () => {
117
- button.props.onPressMain();
118
- });
119
- expect(spyToast).toHaveBeenCalled();
95
+ expect(mockedNavigate).toHaveBeenCalledWith(
96
+ Routes.SetupScriptReceiverNotify,
97
+ {
98
+ automate: route.params.automate,
99
+ unitId: 1,
100
+ formData: { message: 'Message', title: 'Title', unit: 1 },
101
+ }
102
+ );
120
103
  });
121
104
  });
@@ -66,11 +66,12 @@ describe('Test SetupScriptReceiverEmail', () => {
66
66
  });
67
67
  const instance = tree.root;
68
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();
69
+ expect(checkboxs).toHaveLength(3);
70
+ expect(checkboxs[0].props.value).toBeFalsy(); // Select All
71
+ expect(checkboxs[1].props.disabled).toBeFalsy();
72
+ expect(checkboxs[2].props.disabled).toBeTruthy();
72
73
  await act(async () => {
73
- checkboxs[0].props.onValueChange(true);
74
+ checkboxs[1].props.onValueChange(true);
74
75
  });
75
76
 
76
77
  const button = instance.findByType(BottomButtonView);
@@ -89,11 +90,12 @@ describe('Test SetupScriptReceiverEmail', () => {
89
90
  });
90
91
  const instance = tree.root;
91
92
  const checkboxs = instance.findAllByType(CheckBox);
92
- expect(checkboxs).toHaveLength(2);
93
- expect(checkboxs[0].props.disabled).toBeFalsy();
94
- expect(checkboxs[1].props.disabled).toBeTruthy();
93
+ expect(checkboxs).toHaveLength(3);
94
+ expect(checkboxs[0].props.value).toBeFalsy(); // Select All
95
+ expect(checkboxs[1].props.disabled).toBeFalsy();
96
+ expect(checkboxs[2].props.disabled).toBeTruthy();
95
97
  await act(async () => {
96
- checkboxs[0].props.onValueChange(true);
98
+ checkboxs[1].props.onValueChange(true);
97
99
  });
98
100
 
99
101
  const button = instance.findByType(BottomButtonView);