@eohjsc/react-native-smart-city 0.7.27 → 0.7.31
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 +8 -0
- package/src/configs/AccessibilityLabel.js +3 -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/ItemLog.js +1 -0
- 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 +210 -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/EditActionsList/UpdateReceiverEmailScript.js +4 -3
- package/src/screens/Automate/EditActionsList/UpdateReceiverSmsScript.js +5 -4
- package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
- package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +1 -1
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +116 -2
- package/src/screens/Automate/ScriptDetail/index.js +47 -9
- 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/detail.js +14 -6
- package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
- 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 +11 -0
- package/src/utils/I18n/translations/vi.js +11 -0
- package/src/utils/Route/index.js +3 -1
- package/src/utils/Validation.js +5 -0
- package/src/utils/store.js +5 -0
|
@@ -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
|
|
@@ -8,7 +8,7 @@ import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
|
8
8
|
import BottomButtonView from '../../../commons/BottomButtonView';
|
|
9
9
|
import { axiosPut, axiosGet } from '../../../utils/Apis/axios';
|
|
10
10
|
import { API, Colors } from '../../../configs';
|
|
11
|
-
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
11
|
+
import { ToastBottomHelper, shortEmailName } from '../../../utils/Utils';
|
|
12
12
|
import Routes from '../../../utils/Route';
|
|
13
13
|
import moment from 'moment';
|
|
14
14
|
import CheckBox from '@react-native-community/checkbox';
|
|
@@ -110,8 +110,9 @@ const UpdateReceiverEmailScript = ({ route }) => {
|
|
|
110
110
|
}, [share_id, id]);
|
|
111
111
|
|
|
112
112
|
const firstWordsInName = useMemo(() => {
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
const nameTemp = name || shortEmailName(email);
|
|
114
|
+
return nameTemp?.charAt() || '';
|
|
115
|
+
}, [email, name]);
|
|
115
116
|
|
|
116
117
|
const circleColor = arrColor[index % arrColor.length];
|
|
117
118
|
|
|
@@ -8,7 +8,7 @@ import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
|
8
8
|
import BottomButtonView from '../../../commons/BottomButtonView/index.js';
|
|
9
9
|
import { axiosPut, axiosGet } from '../../../utils/Apis/axios.js';
|
|
10
10
|
import { API, Colors } from '../../../configs/index.js';
|
|
11
|
-
import { ToastBottomHelper } from '../../../utils/Utils.js';
|
|
11
|
+
import { ToastBottomHelper, shortEmailName } from '../../../utils/Utils.js';
|
|
12
12
|
import Routes from '../../../utils/Route/index.js';
|
|
13
13
|
import moment from 'moment';
|
|
14
14
|
import CheckBox from '@react-native-community/checkbox';
|
|
@@ -96,7 +96,7 @@ const UpdateReceiverSmsScript = ({ route }) => {
|
|
|
96
96
|
);
|
|
97
97
|
|
|
98
98
|
const RowMember = memo(({ member, index, onValueChange }) => {
|
|
99
|
-
const { id, name, avatar, share_id, phone_number } = member;
|
|
99
|
+
const { id, name, email, avatar, share_id, phone_number } = member;
|
|
100
100
|
const [role, roleColor] = useMemo(() => {
|
|
101
101
|
if (!share_id) {
|
|
102
102
|
return [t('owner'), Colors.Primary];
|
|
@@ -108,8 +108,9 @@ const UpdateReceiverSmsScript = ({ route }) => {
|
|
|
108
108
|
}, [share_id, id]);
|
|
109
109
|
|
|
110
110
|
const firstWordsInName = useMemo(() => {
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const nameTemp = name || shortEmailName(email);
|
|
112
|
+
return nameTemp?.charAt() || '';
|
|
113
|
+
}, [email, name]);
|
|
113
114
|
|
|
114
115
|
const circleColor = arrColor[index % arrColor.length];
|
|
115
116
|
|
|
@@ -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 () => {
|
|
@@ -3,7 +3,7 @@ import { BackHandler, Platform } from 'react-native';
|
|
|
3
3
|
import { create, act } from 'react-test-renderer';
|
|
4
4
|
import Toast from 'react-native-toast-message';
|
|
5
5
|
import { useNavigation } from '@react-navigation/native';
|
|
6
|
-
import {
|
|
6
|
+
import { TouchableOpacity } from 'react-native';
|
|
7
7
|
import MockAdapter from 'axios-mock-adapter';
|
|
8
8
|
|
|
9
9
|
import { SCProvider } from '../../../../context';
|
|
@@ -92,6 +92,7 @@ describe('Test ScriptDetail', () => {
|
|
|
92
92
|
script: {
|
|
93
93
|
name: 'name',
|
|
94
94
|
enable: true,
|
|
95
|
+
enabled_notifications: true,
|
|
95
96
|
},
|
|
96
97
|
},
|
|
97
98
|
},
|
|
@@ -920,7 +921,9 @@ describe('Test ScriptDetail', () => {
|
|
|
920
921
|
tree = await create(wrapComponent(route));
|
|
921
922
|
});
|
|
922
923
|
const instance = tree.root;
|
|
923
|
-
const switchButton = instance.
|
|
924
|
+
const switchButton = instance.findByProps({
|
|
925
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_SCRIPT,
|
|
926
|
+
});
|
|
924
927
|
await act(async () => {
|
|
925
928
|
await switchButton.props.onValueChange(false);
|
|
926
929
|
});
|
|
@@ -939,6 +942,116 @@ describe('Test ScriptDetail', () => {
|
|
|
939
942
|
el.type === TouchableOpacity
|
|
940
943
|
);
|
|
941
944
|
expect(buttonEditScript).toHaveLength(0);
|
|
945
|
+
expect(mock.history.post).toHaveLength(1);
|
|
946
|
+
expect(mock.history.post[0].url).toEqual(API.AUTOMATE.ENABLE_SCRIPT(1));
|
|
947
|
+
});
|
|
948
|
+
|
|
949
|
+
it('test press disable script false', async () => {
|
|
950
|
+
mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
|
|
951
|
+
mock.onPost(API.AUTOMATE.ENABLE_SCRIPT(1)).reply(400);
|
|
952
|
+
await act(async () => {
|
|
953
|
+
tree = await create(wrapComponent(route));
|
|
954
|
+
});
|
|
955
|
+
const instance = tree.root;
|
|
956
|
+
const switchButton = instance.findByProps({
|
|
957
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_SCRIPT,
|
|
958
|
+
});
|
|
959
|
+
expect(switchButton.props.value).toBeTruthy();
|
|
960
|
+
|
|
961
|
+
await act(async () => {
|
|
962
|
+
await switchButton.props.onValueChange(false);
|
|
963
|
+
});
|
|
964
|
+
expect(switchButton.props.value).toBeTruthy();
|
|
965
|
+
const buttonAddScript = instance.findAll(
|
|
966
|
+
(el) =>
|
|
967
|
+
el.props.accessibilityLabel ===
|
|
968
|
+
AccessibilityLabel.BUTTON_ADD_SCRIPT_ACTION &&
|
|
969
|
+
el.type === TouchableOpacity
|
|
970
|
+
);
|
|
971
|
+
expect(buttonAddScript).toHaveLength(1);
|
|
972
|
+
|
|
973
|
+
const buttonEditScript = instance.findAll(
|
|
974
|
+
(el) =>
|
|
975
|
+
el.props.accessibilityLabel ===
|
|
976
|
+
AccessibilityLabel.BUTTON_EDIT_SCRIPT_ACTION &&
|
|
977
|
+
el.type === TouchableOpacity
|
|
978
|
+
);
|
|
979
|
+
expect(buttonEditScript).toHaveLength(1);
|
|
980
|
+
expect(mock.history.post).toHaveLength(1);
|
|
981
|
+
expect(mock.history.post[0].url).toEqual(API.AUTOMATE.ENABLE_SCRIPT(1));
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
it('test enable notifications for script', async () => {
|
|
985
|
+
mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
|
|
986
|
+
mock.onPost(API.AUTOMATE.ENABLE_NOTIFICATIONS(1)).reply(200);
|
|
987
|
+
await act(async () => {
|
|
988
|
+
tree = await create(wrapComponent(route));
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
const instance = tree.root;
|
|
992
|
+
const enableNotificationsSwitch = instance.findByProps({
|
|
993
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
|
|
994
|
+
});
|
|
995
|
+
expect(enableNotificationsSwitch.props.value).toBeTruthy();
|
|
996
|
+
|
|
997
|
+
await act(async () => {
|
|
998
|
+
await enableNotificationsSwitch.props.onValueChange(false);
|
|
999
|
+
});
|
|
1000
|
+
expect(enableNotificationsSwitch.props.value).toBeFalsy();
|
|
1001
|
+
expect(mock.history.post).toHaveLength(1);
|
|
1002
|
+
expect(mock.history.post[0].url).toEqual(
|
|
1003
|
+
API.AUTOMATE.ENABLE_NOTIFICATIONS(1)
|
|
1004
|
+
);
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
it('test enable notifications for script fail', async () => {
|
|
1008
|
+
mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
|
|
1009
|
+
mock.onPost(API.AUTOMATE.ENABLE_NOTIFICATIONS(1)).reply(400);
|
|
1010
|
+
await act(async () => {
|
|
1011
|
+
tree = await create(wrapComponent(route));
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
const instance = tree.root;
|
|
1015
|
+
const enableNotificationsSwitch = instance.findByProps({
|
|
1016
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
|
|
1017
|
+
});
|
|
1018
|
+
expect(enableNotificationsSwitch.props.value).toBeTruthy();
|
|
1019
|
+
|
|
1020
|
+
await act(async () => {
|
|
1021
|
+
await enableNotificationsSwitch.props.onValueChange(false);
|
|
1022
|
+
});
|
|
1023
|
+
expect(enableNotificationsSwitch.props.value).toBeTruthy();
|
|
1024
|
+
expect(mock.history.post).toHaveLength(1);
|
|
1025
|
+
expect(mock.history.post[0].url).toEqual(
|
|
1026
|
+
API.AUTOMATE.ENABLE_NOTIFICATIONS(1)
|
|
1027
|
+
);
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
it('test hidden enable notifications switch when disable script', async () => {
|
|
1031
|
+
mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
|
|
1032
|
+
mock.onPost(API.AUTOMATE.ENABLE_SCRIPT(1)).reply(200, data);
|
|
1033
|
+
await act(async () => {
|
|
1034
|
+
tree = await create(wrapComponent(route));
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
const instance = tree.root;
|
|
1038
|
+
const enableSwitch = instance.findByProps({
|
|
1039
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_SCRIPT,
|
|
1040
|
+
});
|
|
1041
|
+
let enableNotificationsSwitchs = instance.findAllByProps({
|
|
1042
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
|
|
1043
|
+
});
|
|
1044
|
+
expect(enableSwitch.props.value).toBeTruthy();
|
|
1045
|
+
expect(enableNotificationsSwitchs).toHaveLength(1);
|
|
1046
|
+
|
|
1047
|
+
await act(async () => {
|
|
1048
|
+
await enableSwitch.props.onValueChange(false);
|
|
1049
|
+
});
|
|
1050
|
+
expect(enableSwitch.props.value).toBeFalsy();
|
|
1051
|
+
enableNotificationsSwitchs = instance.findAllByProps({
|
|
1052
|
+
accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
|
|
1053
|
+
});
|
|
1054
|
+
expect(enableNotificationsSwitchs).toHaveLength(0);
|
|
942
1055
|
});
|
|
943
1056
|
|
|
944
1057
|
it('test press add action reach limit', async () => {
|
|
@@ -1068,6 +1181,7 @@ describe('Test ScriptDetail', () => {
|
|
|
1068
1181
|
script: {
|
|
1069
1182
|
name: 'name',
|
|
1070
1183
|
enable: true,
|
|
1184
|
+
enabled_notifications: true,
|
|
1071
1185
|
},
|
|
1072
1186
|
};
|
|
1073
1187
|
route.params = {
|
|
@@ -108,10 +108,14 @@ const ScriptDetail = ({ route }) => {
|
|
|
108
108
|
chip_local_control,
|
|
109
109
|
is_local_control,
|
|
110
110
|
chip_id_local_control,
|
|
111
|
+
enabled_notifications,
|
|
111
112
|
} = script || {};
|
|
112
113
|
|
|
113
114
|
const [local_control, setLocalControl] = useState({});
|
|
114
115
|
const [enableScript, setEnableScript] = useState(enable);
|
|
116
|
+
const [enableNotificationsScript, setEnableNotificationsScript] = useState(
|
|
117
|
+
enabled_notifications
|
|
118
|
+
);
|
|
115
119
|
const [listMenuItemCondition, setListMenuItemCondition] = useState([]);
|
|
116
120
|
const [isShowAddCondition, setIsShowAddCondition] = useState(false);
|
|
117
121
|
const permissions = useBackendPermission();
|
|
@@ -289,6 +293,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
289
293
|
if (success) {
|
|
290
294
|
setAutomate(automateData);
|
|
291
295
|
setEnableScript(automateData.script.enable);
|
|
296
|
+
setEnableNotificationsScript(automateData.script.enabled_notifications);
|
|
292
297
|
setNeedAllCondition(automateData.is_need_all_conditions);
|
|
293
298
|
}
|
|
294
299
|
}, [automateId]);
|
|
@@ -330,7 +335,6 @@ const ScriptDetail = ({ route }) => {
|
|
|
330
335
|
|
|
331
336
|
const onChangeSwitch = useCallback(
|
|
332
337
|
async (checked) => {
|
|
333
|
-
setEnableScript(checked);
|
|
334
338
|
const { success } = await axiosPost(
|
|
335
339
|
API.AUTOMATE.ENABLE_SCRIPT(automateId),
|
|
336
340
|
{
|
|
@@ -338,8 +342,24 @@ const ScriptDetail = ({ route }) => {
|
|
|
338
342
|
}
|
|
339
343
|
);
|
|
340
344
|
if (success) {
|
|
341
|
-
ToastBottomHelper.success(t('update_successfully'));
|
|
342
345
|
setEnableScript(checked);
|
|
346
|
+
ToastBottomHelper.success(t('update_successfully'));
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
[automateId, t]
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
const onChangeNotificationsSwitch = useCallback(
|
|
353
|
+
async (checked) => {
|
|
354
|
+
const { success } = await axiosPost(
|
|
355
|
+
API.AUTOMATE.ENABLE_NOTIFICATIONS(automateId),
|
|
356
|
+
{
|
|
357
|
+
enable: checked,
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
if (success) {
|
|
361
|
+
setEnableNotificationsScript(checked);
|
|
362
|
+
ToastBottomHelper.success(t('update_successfully'));
|
|
343
363
|
}
|
|
344
364
|
},
|
|
345
365
|
[automateId, t]
|
|
@@ -680,7 +700,25 @@ const ScriptDetail = ({ route }) => {
|
|
|
680
700
|
<Text type="H3" semibold>
|
|
681
701
|
{t('enable_this_script')}
|
|
682
702
|
</Text>
|
|
683
|
-
<Switch
|
|
703
|
+
<Switch
|
|
704
|
+
value={enableScript}
|
|
705
|
+
onValueChange={onChangeSwitch}
|
|
706
|
+
accessibilityLabel={AccessibilityLabel.SWITCH_ENABLE_SCRIPT}
|
|
707
|
+
/>
|
|
708
|
+
</View>
|
|
709
|
+
)}
|
|
710
|
+
{!!enableScript && (
|
|
711
|
+
<View style={styles.row}>
|
|
712
|
+
<Text type="H3" semibold>
|
|
713
|
+
{t('enable_notifications_for_this_script')}
|
|
714
|
+
</Text>
|
|
715
|
+
<Switch
|
|
716
|
+
value={enableNotificationsScript}
|
|
717
|
+
onValueChange={onChangeNotificationsSwitch}
|
|
718
|
+
accessibilityLabel={
|
|
719
|
+
AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT
|
|
720
|
+
}
|
|
721
|
+
/>
|
|
684
722
|
</View>
|
|
685
723
|
)}
|
|
686
724
|
{renderLocalControl}
|
|
@@ -955,7 +993,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
955
993
|
</View>
|
|
956
994
|
);
|
|
957
995
|
} else if (notify_script) {
|
|
958
|
-
const { title, message, unit_name } = notify_script;
|
|
996
|
+
const { title, message, unit_name, str_receivers } = notify_script;
|
|
959
997
|
return (
|
|
960
998
|
<View style={styles.wrapItem}>
|
|
961
999
|
<View style={styles.leftItem}>
|
|
@@ -978,7 +1016,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
978
1016
|
</View>
|
|
979
1017
|
</View>
|
|
980
1018
|
<Text numberOfLines={1} type="H4" color={color}>
|
|
981
|
-
{unit_name}
|
|
1019
|
+
{`${unit_name}: ${str_receivers}`}
|
|
982
1020
|
</Text>
|
|
983
1021
|
</View>
|
|
984
1022
|
</View>
|
|
@@ -1008,7 +1046,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
1008
1046
|
</View>
|
|
1009
1047
|
);
|
|
1010
1048
|
} else if (email_script) {
|
|
1011
|
-
const { title, message, str_emails } = email_script;
|
|
1049
|
+
const { title, message, unit_name, str_emails } = email_script;
|
|
1012
1050
|
return (
|
|
1013
1051
|
<View style={styles.wrapItem}>
|
|
1014
1052
|
<View style={styles.leftItem}>
|
|
@@ -1031,13 +1069,13 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
1031
1069
|
</View>
|
|
1032
1070
|
</View>
|
|
1033
1071
|
<Text numberOfLines={1} type="H4" color={color}>
|
|
1034
|
-
{str_emails}
|
|
1072
|
+
{`${unit_name}: ${str_emails}`}
|
|
1035
1073
|
</Text>
|
|
1036
1074
|
</View>
|
|
1037
1075
|
</View>
|
|
1038
1076
|
);
|
|
1039
1077
|
} else if (sms_script) {
|
|
1040
|
-
const { message, str_phone_numbers } = sms_script;
|
|
1078
|
+
const { message, unit_name, str_phone_numbers } = sms_script;
|
|
1041
1079
|
color = local_control.is_local_control ? color : Colors.Gray7;
|
|
1042
1080
|
return (
|
|
1043
1081
|
<View style={styles.wrapItem}>
|
|
@@ -1056,7 +1094,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
1056
1094
|
{message}
|
|
1057
1095
|
</Text>
|
|
1058
1096
|
<Text numberOfLines={1} type="H4" color={color}>
|
|
1059
|
-
{str_phone_numbers}
|
|
1097
|
+
{`${unit_name}: ${str_phone_numbers}`}
|
|
1060
1098
|
</Text>
|
|
1061
1099
|
</View>
|
|
1062
1100
|
</View>
|