@eohjsc/react-native-smart-city 0.7.26 → 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.
- package/index.js +2 -0
- package/package.json +2 -1
- package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +68 -0
- package/src/commons/Dashboard/MyDashboardDevice/index.js +46 -11
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +43 -11
- package/src/commons/Dashboard/MyUnit/index.js +40 -32
- package/src/commons/ModalAlert/index.js +51 -0
- package/src/commons/ModalAlert/styles.js +54 -0
- package/src/commons/SubUnit/ShortDetail.js +20 -4
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +46 -1
- package/src/configs/API.js +6 -0
- package/src/configs/AccessibilityLabel.js +1 -0
- package/src/configs/Constants.js +7 -0
- package/src/configs/SCConfig.js +6 -0
- package/src/context/SCContext.tsx +12 -1
- package/src/context/SCStore.ts +14 -0
- package/src/context/actionType.ts +10 -0
- package/src/context/mockStore.ts +30 -1
- package/src/context/reducer.ts +35 -0
- package/src/hooks/IoT/useRemoteControl.js +4 -1
- package/src/hooks/IoT/useWatchSharedChips.js +130 -0
- package/src/hooks/Review/__test__/useInAppReview.test.js +99 -0
- package/src/hooks/Review/useInAppReview.js +70 -0
- package/src/hooks/useMqtt.js +78 -27
- package/src/iot/Monitor.js +149 -26
- package/src/iot/UpdateStates.js +60 -0
- package/src/iot/mqtt.js +177 -22
- package/src/navigations/UnitStack.js +16 -0
- package/src/screens/ActivityLog/FilterPopup.js +4 -79
- package/src/screens/ActivityLog/ItemLog.js +1 -0
- package/src/screens/ActivityLog/__test__/FilterPopup.test.js +2 -6
- package/src/screens/ActivityLog/__test__/index.test.js +51 -29
- package/src/screens/ActivityLog/index.js +0 -1
- package/src/screens/ActivityLog/styles/filterPopupStyles.js +5 -2
- package/src/screens/AddNewGateway/RenameNewDevices.js +5 -0
- package/src/screens/AddNewGateway/__test__/RenameNewDevices.test.js +18 -0
- package/src/screens/Automate/AddNewAction/ReceiverSelect.js +208 -0
- package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +1 -1
- package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +18 -28
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +22 -129
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverNotify.js +59 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +22 -129
- package/src/screens/Automate/AddNewAction/SetupScriptSms.js +1 -1
- package/src/screens/Automate/AddNewAction/Styles/{SetupScriptReceiverEmailStyles.js → ReceiverSelectStyles.js} +18 -1
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +16 -33
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +10 -8
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverNotify.test.js +217 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +10 -8
- package/src/screens/Automate/Components/InputName.js +5 -1
- package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
- package/src/screens/Automate/ScriptDetail/index.js +6 -6
- package/src/screens/CreatePassword/__test__/index.test.js +133 -0
- package/src/screens/CreatePassword/index.js +134 -0
- package/src/screens/CreatePassword/styles.js +45 -0
- package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +447 -0
- package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +344 -0
- package/src/screens/Device/__test__/{mqttDetail.test.js → DeviceDetail-modbus.test.js} +287 -320
- package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +451 -0
- package/src/screens/Device/__test__/DeviceDetail.test.js +502 -0
- package/src/screens/Device/__test__/detail.test.js +61 -3
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +28 -3
- package/src/screens/Device/components/SensorDisplayItem.js +16 -14
- package/src/screens/Device/detail.js +14 -6
- package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
- package/src/screens/Device/styles.js +0 -5
- package/src/screens/EnterPassword/__test__/EnterPassword.test.js +76 -1
- package/src/screens/EnterPassword/index.js +34 -4
- package/src/screens/EnterPassword/styles.js +1 -1
- package/src/utils/FactoryGateway.js +597 -0
- package/src/utils/I18n/translations/en.js +10 -0
- package/src/utils/I18n/translations/vi.js +10 -0
- package/src/utils/Route/index.js +3 -1
- package/src/utils/Validation.js +5 -0
- package/src/utils/store.js +5 -0
|
@@ -1,41 +1,20 @@
|
|
|
1
|
-
import React, { useCallback,
|
|
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
|
|
9
|
-
import {
|
|
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 {
|
|
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
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
<
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
|
|
@@ -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(
|
|
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(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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(
|
|
70
|
-
expect(checkboxs[0].props.
|
|
71
|
-
expect(checkboxs[1].props.disabled).
|
|
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[
|
|
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(
|
|
93
|
-
expect(checkboxs[0].props.
|
|
94
|
-
expect(checkboxs[1].props.disabled).
|
|
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[
|
|
98
|
+
checkboxs[1].props.onValueChange(true);
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
const button = instance.findByType(BottomButtonView);
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
2
|
+
import { FlatList } from 'react-native';
|
|
3
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import renderer, { act } from 'react-test-renderer';
|
|
6
|
+
import BottomButtonView from '../../../../commons/BottomButtonView';
|
|
7
|
+
import API from '../../../../configs/API';
|
|
8
|
+
import { SCProvider } from '../../../../context';
|
|
9
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
10
|
+
import { Search } from '../../../../commons/DevMode';
|
|
11
|
+
import api from '../../../../utils/Apis/axios';
|
|
12
|
+
import Routes from '../../../../utils/Route';
|
|
13
|
+
import { getTranslate } from '../../../../utils/I18n';
|
|
14
|
+
import { ToastBottomHelper } from '../../../../utils/Utils';
|
|
15
|
+
import ReceiverSelect from '../ReceiverSelect';
|
|
16
|
+
import SetupScriptReceiverNotify from '../SetupScriptReceiverNotify';
|
|
17
|
+
import CheckBox from '@react-native-community/checkbox';
|
|
18
|
+
|
|
19
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
20
|
+
|
|
21
|
+
const wrapComponent = (route) => (
|
|
22
|
+
<SCProvider initState={mockSCStore({})}>
|
|
23
|
+
<SetupScriptReceiverNotify route={route} />
|
|
24
|
+
</SCProvider>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
describe('Test SetupScriptReceiverNotify', () => {
|
|
28
|
+
const mockedNavigate = useNavigation().navigate;
|
|
29
|
+
const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
|
|
30
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
31
|
+
|
|
32
|
+
let tree;
|
|
33
|
+
const route = {
|
|
34
|
+
params: {
|
|
35
|
+
unitId: 1,
|
|
36
|
+
automateId: 1,
|
|
37
|
+
automate: {
|
|
38
|
+
id: 1,
|
|
39
|
+
sensor_id: 1,
|
|
40
|
+
},
|
|
41
|
+
closeScreen: Routes.ScriptDetail,
|
|
42
|
+
formData: { title: 'title', message: 'message' },
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const listUser = [
|
|
47
|
+
{
|
|
48
|
+
id: 1,
|
|
49
|
+
avatar: 'https://image.com',
|
|
50
|
+
email: 'user1@eoh.io',
|
|
51
|
+
name: 'User 1',
|
|
52
|
+
phone_number: null,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 2,
|
|
56
|
+
avatar: null,
|
|
57
|
+
email: null,
|
|
58
|
+
name: 'User 2',
|
|
59
|
+
phone_number: '090xxx',
|
|
60
|
+
share_id: 3,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
mockedNavigate.mockClear();
|
|
65
|
+
useRoute.mockImplementation(() => route);
|
|
66
|
+
spyToastSuccess.mockClear();
|
|
67
|
+
spyToastError.mockClear();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('test create script notify success', async () => {
|
|
71
|
+
mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
|
|
72
|
+
mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(200);
|
|
73
|
+
await act(async () => {
|
|
74
|
+
tree = await renderer.create(wrapComponent(route));
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const instance = tree.root;
|
|
78
|
+
let checkboxs = instance.findAllByType(CheckBox);
|
|
79
|
+
expect(checkboxs).toHaveLength(3);
|
|
80
|
+
expect(checkboxs[0].props.value).toBeFalsy(); // Select All
|
|
81
|
+
expect(checkboxs[1].props.disabled).toBeFalsy();
|
|
82
|
+
expect(checkboxs[2].props.disabled).toBeFalsy();
|
|
83
|
+
|
|
84
|
+
const receiverSelect = instance.findByType(ReceiverSelect);
|
|
85
|
+
expect(receiverSelect.props.listUser).toEqual([]);
|
|
86
|
+
|
|
87
|
+
await act(async () => {
|
|
88
|
+
checkboxs[1].props.onValueChange(true);
|
|
89
|
+
});
|
|
90
|
+
expect(checkboxs[0].props.value).toBeFalsy();
|
|
91
|
+
expect(receiverSelect.props.listUser).toEqual([1]);
|
|
92
|
+
|
|
93
|
+
checkboxs = instance.findAllByType(CheckBox);
|
|
94
|
+
await act(async () => {
|
|
95
|
+
checkboxs[2].props.onValueChange(true);
|
|
96
|
+
});
|
|
97
|
+
expect(checkboxs[0].props.value).toBeTruthy();
|
|
98
|
+
|
|
99
|
+
checkboxs = instance.findAllByType(CheckBox);
|
|
100
|
+
await act(async () => {
|
|
101
|
+
checkboxs[2].props.onValueChange(false);
|
|
102
|
+
});
|
|
103
|
+
expect(checkboxs[0].props.value).toBeFalsy();
|
|
104
|
+
|
|
105
|
+
const button = instance.findByType(BottomButtonView);
|
|
106
|
+
await act(async () => {
|
|
107
|
+
button.props.onPressMain();
|
|
108
|
+
});
|
|
109
|
+
expect(mock.history.post).toHaveLength(1);
|
|
110
|
+
expect(mock.history.post[0].url).toEqual(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1));
|
|
111
|
+
expect(mock.history.post[0].data).toEqual(
|
|
112
|
+
JSON.stringify({
|
|
113
|
+
title: 'title',
|
|
114
|
+
message: 'message',
|
|
115
|
+
receiver: [1],
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
expect(spyToastSuccess).toHaveBeenCalledWith(
|
|
119
|
+
getTranslate('en', 'text_done')
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('test filter select all and deselect all', async () => {
|
|
124
|
+
mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
|
|
125
|
+
await act(async () => {
|
|
126
|
+
tree = await renderer.create(wrapComponent(route));
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const instance = tree.root;
|
|
130
|
+
let checkboxs = instance.findAllByType(CheckBox);
|
|
131
|
+
expect(checkboxs).toHaveLength(3);
|
|
132
|
+
expect(checkboxs[0].props.value).toBeFalsy(); // Select All
|
|
133
|
+
expect(checkboxs[1].props.disabled).toBeFalsy();
|
|
134
|
+
expect(checkboxs[2].props.disabled).toBeFalsy();
|
|
135
|
+
|
|
136
|
+
const flatList = instance.findByType(FlatList);
|
|
137
|
+
expect(flatList.props.data).toEqual([
|
|
138
|
+
{
|
|
139
|
+
...listUser[0],
|
|
140
|
+
label: null,
|
|
141
|
+
invalidLabel: getTranslate('en', 'no_phone_number'),
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
...listUser[1],
|
|
145
|
+
label: '090xxx',
|
|
146
|
+
invalidLabel: getTranslate('en', 'no_phone_number'),
|
|
147
|
+
},
|
|
148
|
+
]);
|
|
149
|
+
|
|
150
|
+
const search = instance.findByType(Search);
|
|
151
|
+
await act(async () => {
|
|
152
|
+
search.props.onSearch('User 1');
|
|
153
|
+
});
|
|
154
|
+
expect(flatList.props.data).toEqual([
|
|
155
|
+
{
|
|
156
|
+
...listUser[0],
|
|
157
|
+
label: null,
|
|
158
|
+
invalidLabel: getTranslate('en', 'no_phone_number'),
|
|
159
|
+
},
|
|
160
|
+
]);
|
|
161
|
+
|
|
162
|
+
await act(async () => {
|
|
163
|
+
search.props.onSearch('090');
|
|
164
|
+
});
|
|
165
|
+
expect(flatList.props.data).toEqual([
|
|
166
|
+
{
|
|
167
|
+
...listUser[1],
|
|
168
|
+
label: '090xxx',
|
|
169
|
+
invalidLabel: getTranslate('en', 'no_phone_number'),
|
|
170
|
+
},
|
|
171
|
+
]);
|
|
172
|
+
|
|
173
|
+
await act(async () => {
|
|
174
|
+
search.props.onSearch('');
|
|
175
|
+
});
|
|
176
|
+
await act(async () => {
|
|
177
|
+
checkboxs[0].props.onValueChange(true); // Select All
|
|
178
|
+
});
|
|
179
|
+
checkboxs = instance.findAllByType(CheckBox);
|
|
180
|
+
expect(checkboxs[0].props.value).toBeTruthy();
|
|
181
|
+
expect(checkboxs[1].props.value).toBeTruthy();
|
|
182
|
+
expect(checkboxs[2].props.value).toBeTruthy();
|
|
183
|
+
|
|
184
|
+
await act(async () => {
|
|
185
|
+
checkboxs[0].props.onValueChange(false); // Deselect All
|
|
186
|
+
});
|
|
187
|
+
checkboxs = instance.findAllByType(CheckBox);
|
|
188
|
+
expect(checkboxs[0].props.value).toBeFalsy();
|
|
189
|
+
expect(checkboxs[1].props.value).toBeFalsy();
|
|
190
|
+
expect(checkboxs[2].props.value).toBeFalsy();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('test create script notify fail', async () => {
|
|
194
|
+
mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
|
|
195
|
+
mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(400);
|
|
196
|
+
await act(async () => {
|
|
197
|
+
tree = await renderer.create(wrapComponent(route));
|
|
198
|
+
});
|
|
199
|
+
const instance = tree.root;
|
|
200
|
+
const checkboxs = instance.findAllByType(CheckBox);
|
|
201
|
+
expect(checkboxs).toHaveLength(3);
|
|
202
|
+
expect(checkboxs[0].props.value).toBeFalsy(); // Select All
|
|
203
|
+
expect(checkboxs[1].props.disabled).toBeFalsy();
|
|
204
|
+
expect(checkboxs[2].props.disabled).toBeFalsy();
|
|
205
|
+
await act(async () => {
|
|
206
|
+
checkboxs[1].props.onValueChange(true);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const button = instance.findByType(BottomButtonView);
|
|
210
|
+
await act(async () => {
|
|
211
|
+
button.props.onPressMain();
|
|
212
|
+
});
|
|
213
|
+
expect(spyToastError).toHaveBeenCalledWith(
|
|
214
|
+
getTranslate('en', 'error_please_try_later')
|
|
215
|
+
);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
@@ -66,11 +66,12 @@ describe('Test SetupScriptReceiverSms', () => {
|
|
|
66
66
|
});
|
|
67
67
|
const instance = tree.root;
|
|
68
68
|
const checkboxs = instance.findAllByType(CheckBox);
|
|
69
|
-
expect(checkboxs).toHaveLength(
|
|
70
|
-
expect(checkboxs[0].props.
|
|
71
|
-
expect(checkboxs[1].props.disabled).
|
|
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[
|
|
74
|
+
checkboxs[1].props.onValueChange(true);
|
|
74
75
|
});
|
|
75
76
|
|
|
76
77
|
const button = instance.findByType(BottomButtonView);
|
|
@@ -89,11 +90,12 @@ describe('Test SetupScriptReceiverSms', () => {
|
|
|
89
90
|
});
|
|
90
91
|
const instance = tree.root;
|
|
91
92
|
const checkboxs = instance.findAllByType(CheckBox);
|
|
92
|
-
expect(checkboxs).toHaveLength(
|
|
93
|
-
expect(checkboxs[0].props.
|
|
94
|
-
expect(checkboxs[1].props.disabled).
|
|
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[
|
|
98
|
+
checkboxs[1].props.onValueChange(true);
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
const button = instance.findByType(BottomButtonView);
|
|
@@ -6,6 +6,7 @@ import { API } from '../../../configs';
|
|
|
6
6
|
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
7
7
|
import _TextInput from '../../../commons/Form/TextInput';
|
|
8
8
|
import styles from './InputNameStyles';
|
|
9
|
+
import useInAppReview from '../../../hooks/Review/useInAppReview';
|
|
9
10
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
10
11
|
import { axiosPost } from '../../../utils/Apis/axios';
|
|
11
12
|
import NewActionWrapper from '../../Automate/AddNewAction/NewActionWrapper';
|
|
@@ -18,6 +19,8 @@ const InputName = ({ title, placeholder }) => {
|
|
|
18
19
|
const { navigate } = useNavigation();
|
|
19
20
|
const [name, setName] = useState(automateName);
|
|
20
21
|
const [processing, setProcessing] = useState(false);
|
|
22
|
+
const { allowInAppReview } = useInAppReview(false);
|
|
23
|
+
|
|
21
24
|
const handleContinue = useCallback(async () => {
|
|
22
25
|
if (processing) {
|
|
23
26
|
/* istanbul ignore next */
|
|
@@ -37,6 +40,7 @@ const InputName = ({ title, placeholder }) => {
|
|
|
37
40
|
);
|
|
38
41
|
|
|
39
42
|
if (success) {
|
|
43
|
+
allowInAppReview();
|
|
40
44
|
navigate({
|
|
41
45
|
name: Routes.ScriptDetail,
|
|
42
46
|
merge: true,
|
|
@@ -47,7 +51,7 @@ const InputName = ({ title, placeholder }) => {
|
|
|
47
51
|
});
|
|
48
52
|
}
|
|
49
53
|
setProcessing(false);
|
|
50
|
-
}, [processing, automate, name, navigate, closeScreen]);
|
|
54
|
+
}, [processing, automate, name, navigate, closeScreen, allowInAppReview]);
|
|
51
55
|
|
|
52
56
|
return (
|
|
53
57
|
<NewActionWrapper
|
|
@@ -12,6 +12,18 @@ import api from '../../../../utils/Apis/axios';
|
|
|
12
12
|
import Routes from '../../../../utils/Route';
|
|
13
13
|
import AddNewOneTap from '../index';
|
|
14
14
|
|
|
15
|
+
const mockAllowInAppReview = jest.fn();
|
|
16
|
+
const mockAskReview = jest.fn();
|
|
17
|
+
jest.mock('../../../../hooks/Review/useInAppReview', () => {
|
|
18
|
+
return {
|
|
19
|
+
__esModule: true,
|
|
20
|
+
default: jest.fn(() => ({
|
|
21
|
+
allowInAppReview: mockAllowInAppReview,
|
|
22
|
+
askReview: mockAskReview,
|
|
23
|
+
})),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
|
|
15
27
|
const wrapComponent = (route) => {
|
|
16
28
|
useRoute.mockReturnValue(route);
|
|
17
29
|
return (
|
|
@@ -28,6 +40,8 @@ describe('test OneTap', () => {
|
|
|
28
40
|
const mockedNavigate = useNavigation().navigate;
|
|
29
41
|
beforeEach(() => {
|
|
30
42
|
mockedNavigate.mockClear();
|
|
43
|
+
mockAllowInAppReview.mockClear();
|
|
44
|
+
mockAskReview.mockClear();
|
|
31
45
|
});
|
|
32
46
|
|
|
33
47
|
it('create OneTap success', async () => {
|
|
@@ -91,6 +105,8 @@ describe('test OneTap', () => {
|
|
|
91
105
|
},
|
|
92
106
|
},
|
|
93
107
|
});
|
|
108
|
+
expect(mockAllowInAppReview).toHaveBeenCalled();
|
|
109
|
+
expect(mockAskReview).not.toHaveBeenCalled();
|
|
94
110
|
});
|
|
95
111
|
|
|
96
112
|
it('create OneTap fail', async () => {
|
|
@@ -116,6 +132,8 @@ describe('test OneTap', () => {
|
|
|
116
132
|
await item[0].props.onPress();
|
|
117
133
|
});
|
|
118
134
|
expect(global.mockedNavigate).not.toHaveBeenCalled();
|
|
135
|
+
expect(mockAllowInAppReview).not.toHaveBeenCalled();
|
|
136
|
+
expect(mockAskReview).not.toHaveBeenCalled();
|
|
119
137
|
});
|
|
120
138
|
|
|
121
139
|
it('test onClose have automateId', async () => {
|