@eohjsc/react-native-smart-city 0.3.93 → 0.3.94
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/package.json +1 -1
- package/src/commons/SubUnit/OneTap/ItemOneTap.js +83 -85
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +68 -24
- package/src/commons/SubUnit/OneTap/index.js +21 -1
- package/src/configs/API.js +1 -0
- package/src/screens/AddNewGateway/ConnectingDevice.js +7 -0
- package/src/screens/AddNewGateway/RenameNewDevices.js +2 -2
- package/src/screens/AddNewGateway/SelectDeviceType.js +67 -9
- package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +35 -0
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +183 -29
- package/src/screens/Automate/MultiUnits.js +28 -18
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +36 -2
- package/src/screens/Automate/ScriptDetail/index.js +17 -3
- package/src/screens/Automate/Styles/MultiUnitsStyles.js +1 -1
- package/src/screens/Automate/__test__/MultiUnits.test.js +63 -6
- package/src/screens/Automate/__test__/index.test.js +44 -10
- package/src/screens/Automate/index.js +53 -38
- package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +24 -1
- package/src/screens/Sharing/InfoMemberUnit.js +2 -2
- package/src/screens/Sharing/MemberList.js +28 -7
- package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +32 -18
- package/src/screens/Sharing/__test__/MemberList.test.js +37 -4
- package/src/screens/Unit/AddMenu.js +42 -19
- package/src/screens/Unit/__test__/AddMenu.test.js +68 -15
- package/src/screens/Unit/components/AutomateScript/index.js +1 -1
- package/src/utils/I18n/translations/en.js +1409 -0
- package/src/utils/I18n/translations/vi.js +1411 -0
- package/src/utils/I18n/translations.ts +2 -2
- package/src/utils/Permission/backend.js +7 -0
- package/src/screens/Sharing/__test__/MemberList2.test.js +0 -74
- package/src/utils/I18n/translations/en.json +0 -1142
- package/src/utils/I18n/translations/vi.json +0 -1139
|
@@ -8,36 +8,30 @@ import Routes from '../../../utils/Route';
|
|
|
8
8
|
import { TouchableOpacity } from 'react-native';
|
|
9
9
|
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
10
10
|
import { ViewButtonBottom } from '../../../commons';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
import { useNavigation } from '@react-navigation/native';
|
|
12
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
13
|
+
import api from '../../../utils/Apis/axios';
|
|
14
|
+
import API from '../../../configs/API';
|
|
15
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
16
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
17
|
+
const wrapComponent = (route, storeData = {}) => (
|
|
18
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
14
19
|
<SelectDeviceType route={route} />
|
|
15
20
|
</SCProvider>
|
|
16
21
|
);
|
|
17
22
|
|
|
18
|
-
const
|
|
19
|
-
const mockedGoBack = jest.fn();
|
|
20
|
-
|
|
21
|
-
jest.mock('@react-navigation/native', () => {
|
|
22
|
-
return {
|
|
23
|
-
...jest.requireActual('@react-navigation/native'),
|
|
24
|
-
useNavigation: () => ({
|
|
25
|
-
navigate: mockedNavigate,
|
|
26
|
-
goBack: mockedGoBack,
|
|
27
|
-
}),
|
|
28
|
-
useIsFocused: () => true,
|
|
29
|
-
};
|
|
30
|
-
});
|
|
23
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
31
24
|
|
|
32
25
|
describe('Test select device type', () => {
|
|
33
26
|
let tree;
|
|
34
27
|
let route;
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
29
|
+
const mockedNavigate = useNavigation().navigate;
|
|
30
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
39
31
|
|
|
40
32
|
beforeEach(() => {
|
|
33
|
+
spyToastError.mockClear();
|
|
34
|
+
mockedNavigate.mockClear();
|
|
41
35
|
route = {
|
|
42
36
|
params: {
|
|
43
37
|
unitId: 1,
|
|
@@ -81,9 +75,9 @@ describe('Test select device type', () => {
|
|
|
81
75
|
expect(deviceTypeItems).toHaveLength(3);
|
|
82
76
|
});
|
|
83
77
|
|
|
84
|
-
const selectDeviceType = async (index) => {
|
|
78
|
+
const selectDeviceType = async (index, storeData = {}) => {
|
|
85
79
|
await act(async () => {
|
|
86
|
-
tree = await create(wrapComponent(route));
|
|
80
|
+
tree = await create(wrapComponent(route, storeData));
|
|
87
81
|
});
|
|
88
82
|
const instance = tree.root;
|
|
89
83
|
const deviceTypeItems = instance.findAll(
|
|
@@ -99,24 +93,184 @@ describe('Test select device type', () => {
|
|
|
99
93
|
await act(async () => {
|
|
100
94
|
submitButton.props.onRightClick();
|
|
101
95
|
});
|
|
102
|
-
|
|
103
|
-
expect(mockedNavigate).toBeCalled();
|
|
104
96
|
};
|
|
105
97
|
|
|
106
98
|
it('select modbus', async () => {
|
|
107
|
-
await selectDeviceType(
|
|
108
|
-
|
|
99
|
+
await selectDeviceType(2, {
|
|
100
|
+
auth: {
|
|
101
|
+
account: {
|
|
102
|
+
user: {
|
|
103
|
+
permissions: {
|
|
104
|
+
plug_and_play_modbus: true,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
expect(mockedNavigate).toBeCalled();
|
|
111
|
+
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
|
|
109
112
|
});
|
|
113
|
+
|
|
110
114
|
it('select zigbee', async () => {
|
|
111
|
-
await selectDeviceType(
|
|
115
|
+
await selectDeviceType(3, {
|
|
116
|
+
auth: {
|
|
117
|
+
account: {
|
|
118
|
+
user: {
|
|
119
|
+
permissions: {
|
|
120
|
+
plug_and_play_zigbee: true,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
expect(mockedNavigate).toBeCalled();
|
|
112
127
|
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
|
|
113
128
|
});
|
|
129
|
+
|
|
130
|
+
it('select zigbee reach limit', async () => {
|
|
131
|
+
mock.onGet(API.DEV_MODE.GATEWAY.COUNT()).reply(200, {
|
|
132
|
+
total_chips: 1,
|
|
133
|
+
total_configs: 1,
|
|
134
|
+
});
|
|
135
|
+
await selectDeviceType(3, {
|
|
136
|
+
auth: {
|
|
137
|
+
account: {
|
|
138
|
+
user: {
|
|
139
|
+
permissions: {
|
|
140
|
+
max_chips_per_unit: 1,
|
|
141
|
+
max_configs_per_unit: 1,
|
|
142
|
+
plug_and_play_zigbee: true,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
149
|
+
expect(spyToastError).toBeCalledWith(
|
|
150
|
+
getTranslate('en', 'reach_max_configs_per_unit')
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
114
154
|
it('select gateway', async () => {
|
|
115
|
-
await selectDeviceType(
|
|
116
|
-
|
|
155
|
+
await selectDeviceType(0, {
|
|
156
|
+
auth: {
|
|
157
|
+
account: {
|
|
158
|
+
user: {
|
|
159
|
+
permissions: {
|
|
160
|
+
plug_and_play_gateway: true,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
expect(mockedNavigate).toBeCalled();
|
|
167
|
+
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.ScanGatewayQR);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('select gateway reach limit', async () => {
|
|
171
|
+
mock.onGet(API.DEV_MODE.GATEWAY.COUNT()).reply(200, {
|
|
172
|
+
total_chips: 1,
|
|
173
|
+
total_configs: 1,
|
|
174
|
+
});
|
|
175
|
+
await selectDeviceType(0, {
|
|
176
|
+
auth: {
|
|
177
|
+
account: {
|
|
178
|
+
user: {
|
|
179
|
+
permissions: {
|
|
180
|
+
max_chips_per_unit: 1,
|
|
181
|
+
plug_and_play_gateway: true,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
188
|
+
expect(spyToastError).toBeCalledWith(
|
|
189
|
+
getTranslate('en', 'reach_max_chips_per_unit')
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('select gateway without permission', async () => {
|
|
194
|
+
await selectDeviceType(0, {
|
|
195
|
+
auth: {
|
|
196
|
+
account: {
|
|
197
|
+
user: {
|
|
198
|
+
permissions: {
|
|
199
|
+
plug_and_play_gateway: false,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
expect(spyToastError).toBeCalledWith(
|
|
206
|
+
getTranslate('en', 'no_permission_plug_and_play_gateway')
|
|
207
|
+
);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('select zigbee without permission', async () => {
|
|
211
|
+
await selectDeviceType(3, {
|
|
212
|
+
auth: {
|
|
213
|
+
account: {
|
|
214
|
+
user: {
|
|
215
|
+
permissions: {
|
|
216
|
+
plug_and_play_zigbee: false,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
expect(spyToastError).toBeCalledWith(
|
|
223
|
+
getTranslate('en', 'no_permission_plug_and_play_zigbee')
|
|
224
|
+
);
|
|
117
225
|
});
|
|
226
|
+
|
|
227
|
+
it('select wifi without permission', async () => {
|
|
228
|
+
await selectDeviceType(1, {
|
|
229
|
+
auth: {
|
|
230
|
+
account: {
|
|
231
|
+
user: {
|
|
232
|
+
permissions: {
|
|
233
|
+
plug_and_play_wifi: false,
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
expect(spyToastError).toBeCalledWith(
|
|
240
|
+
getTranslate('en', 'no_permission_plug_and_play_wifi')
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('select modbus without permission', async () => {
|
|
245
|
+
await selectDeviceType(2, {
|
|
246
|
+
auth: {
|
|
247
|
+
account: {
|
|
248
|
+
user: {
|
|
249
|
+
permissions: {
|
|
250
|
+
plug_and_play_modbus: false,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
expect(spyToastError).toBeCalledWith(
|
|
257
|
+
getTranslate('en', 'no_permission_plug_and_play_modbus')
|
|
258
|
+
);
|
|
259
|
+
});
|
|
260
|
+
|
|
118
261
|
it('select wifi', async () => {
|
|
119
|
-
await selectDeviceType(
|
|
262
|
+
await selectDeviceType(1, {
|
|
263
|
+
auth: {
|
|
264
|
+
account: {
|
|
265
|
+
user: {
|
|
266
|
+
permissions: {
|
|
267
|
+
plug_and_play_wifi: true,
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
expect(mockedNavigate).toBeCalled();
|
|
120
274
|
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
|
|
121
275
|
});
|
|
122
276
|
});
|
|
@@ -17,20 +17,17 @@ import { AUTOMATE_TABS, AUTOMATE_TYPE } from '../../configs/Constants';
|
|
|
17
17
|
import ItemOneTap from '../../commons/SubUnit/OneTap/ItemOneTap';
|
|
18
18
|
import Routes from '../../utils/Route';
|
|
19
19
|
import ItemAddNew from '../../commons/Device/ItemAddNew';
|
|
20
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
21
|
+
import { useBackendPermission } from '../../utils/Permission/backend';
|
|
20
22
|
|
|
21
23
|
const MultiUnits = () => {
|
|
22
24
|
const t = useTranslations();
|
|
23
25
|
const isFocused = useIsFocused();
|
|
24
26
|
const { navigate } = useNavigation();
|
|
25
27
|
const { params = {}, name: currentRouteName } = useRoute();
|
|
26
|
-
const {
|
|
27
|
-
isMultiUnits = false,
|
|
28
|
-
unitName = '',
|
|
29
|
-
unit,
|
|
30
|
-
isOwner,
|
|
31
|
-
newAutomate,
|
|
32
|
-
} = params;
|
|
28
|
+
const { unit, newAutomate } = params;
|
|
33
29
|
const [data, setData] = useState([]);
|
|
30
|
+
const permissions = useBackendPermission();
|
|
34
31
|
|
|
35
32
|
const [tabActive, setTabActive] = useState(AUTOMATE_TABS.SCENARIO);
|
|
36
33
|
|
|
@@ -40,20 +37,20 @@ const MultiUnits = () => {
|
|
|
40
37
|
|
|
41
38
|
const getData = useCallback(
|
|
42
39
|
async (fetchParams) => {
|
|
43
|
-
if (
|
|
40
|
+
if (unit?.id) {
|
|
41
|
+
await fetchWithCache(API.UNIT.AUTOMATE(unit?.id), {}, (response) => {
|
|
42
|
+
const { success, data: automateData } = response;
|
|
43
|
+
success && setData(automateData);
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
44
46
|
const { success, data: automateData } = await axiosGet(
|
|
45
47
|
API.AUTOMATE.GET_MULTI_UNITS(),
|
|
46
48
|
fetchParams
|
|
47
49
|
);
|
|
48
50
|
success && setData(automateData);
|
|
49
|
-
} else {
|
|
50
|
-
await fetchWithCache(API.UNIT.AUTOMATE(unit?.id), {}, (response) => {
|
|
51
|
-
const { success, data: automateData } = response;
|
|
52
|
-
success && setData(automateData);
|
|
53
|
-
});
|
|
54
51
|
}
|
|
55
52
|
},
|
|
56
|
-
[
|
|
53
|
+
[unit?.id]
|
|
57
54
|
);
|
|
58
55
|
|
|
59
56
|
const onPressTabName = (tab) => () => {
|
|
@@ -79,6 +76,12 @@ const MultiUnits = () => {
|
|
|
79
76
|
}, [newAutomate, onPressItem]);
|
|
80
77
|
|
|
81
78
|
const handleOnAddNew = useCallback(() => {
|
|
79
|
+
if (unit?.id) {
|
|
80
|
+
if (permissions?.max_automations_per_unit <= data.length) {
|
|
81
|
+
ToastBottomHelper.error(t('reach_max_automations_per_unit'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
82
85
|
if (tabActive === AUTOMATE_TABS.SCENARIO) {
|
|
83
86
|
navigate(Routes.UnitStack, {
|
|
84
87
|
screen: Routes.ScenarioName,
|
|
@@ -97,7 +100,15 @@ const MultiUnits = () => {
|
|
|
97
100
|
closeScreen: currentRouteName,
|
|
98
101
|
},
|
|
99
102
|
});
|
|
100
|
-
}, [
|
|
103
|
+
}, [
|
|
104
|
+
currentRouteName,
|
|
105
|
+
data.length,
|
|
106
|
+
navigate,
|
|
107
|
+
permissions?.max_automations_per_unit,
|
|
108
|
+
t,
|
|
109
|
+
tabActive,
|
|
110
|
+
unit?.id,
|
|
111
|
+
]);
|
|
101
112
|
|
|
102
113
|
const renderContent = useMemo(() => {
|
|
103
114
|
const listItems = data.filter((item) =>
|
|
@@ -116,11 +127,10 @@ const MultiUnits = () => {
|
|
|
116
127
|
{sortedListItems.map((item, index) => (
|
|
117
128
|
<ItemOneTap
|
|
118
129
|
key={(item?.id || index).toString()}
|
|
119
|
-
isOwner={isOwner}
|
|
120
130
|
automate={item}
|
|
121
131
|
wrapSyles={[
|
|
122
132
|
styles.wrapAutomateItem,
|
|
123
|
-
index % 2 === 0 && styles.
|
|
133
|
+
index % 2 === 0 && styles.itemOneTapMargin,
|
|
124
134
|
]}
|
|
125
135
|
onPressItem={() => onPressItem(item)}
|
|
126
136
|
/>
|
|
@@ -142,7 +152,7 @@ const MultiUnits = () => {
|
|
|
142
152
|
return (
|
|
143
153
|
<View style={styles.wrap}>
|
|
144
154
|
<WrapHeaderScrollable
|
|
145
|
-
title={
|
|
155
|
+
title={unit?.id ? unit?.name : t('multi_units_automate')}
|
|
146
156
|
headerAniStyle={styles.headerAniStyle}
|
|
147
157
|
>
|
|
148
158
|
<View style={styles.wrapContent}>
|
|
@@ -24,8 +24,8 @@ import Text from '../../../../commons/Text';
|
|
|
24
24
|
import { ToastBottomHelper } from '../../../../utils/Utils';
|
|
25
25
|
import { getTranslate } from '../../../../utils/I18n';
|
|
26
26
|
|
|
27
|
-
const wrapComponent = (route) => (
|
|
28
|
-
<SCProvider initState={mockSCStore(
|
|
27
|
+
const wrapComponent = (route, storeData = {}) => (
|
|
28
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
29
29
|
<ScriptDetail route={route} />
|
|
30
30
|
</SCProvider>
|
|
31
31
|
);
|
|
@@ -241,6 +241,40 @@ describe('Test ScriptDetail', () => {
|
|
|
241
241
|
});
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
it('test press add action reach limit', async () => {
|
|
245
|
+
mock.onGet(API.AUTOMATE.SCRIPT(1)).reply(200, data);
|
|
246
|
+
await act(async () => {
|
|
247
|
+
tree = await create(
|
|
248
|
+
wrapComponent(route, {
|
|
249
|
+
auth: {
|
|
250
|
+
account: {
|
|
251
|
+
user: {
|
|
252
|
+
permissions: {
|
|
253
|
+
max_actions_per_automation: 0,
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
const instance = tree.root;
|
|
262
|
+
const button = instance.find(
|
|
263
|
+
(el) =>
|
|
264
|
+
el.props.accessibilityLabel ===
|
|
265
|
+
AccessibilityLabel.BUTTON_ADD_SCRIPT_ACTION &&
|
|
266
|
+
el.type === TouchableOpacity
|
|
267
|
+
);
|
|
268
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
269
|
+
await act(async () => {
|
|
270
|
+
await button.props.onPress();
|
|
271
|
+
});
|
|
272
|
+
expect(mockNavigate).not.toBeCalled();
|
|
273
|
+
expect(spyToastError).toBeCalledWith(
|
|
274
|
+
getTranslate('en', 'reach_max_actions_per_automation')
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
244
278
|
it('test not see add action', async () => {
|
|
245
279
|
route.params.preAutomate.can_edit = false;
|
|
246
280
|
mock.onGet(API.AUTOMATE.SCRIPT(1)).reply(200, data);
|
|
@@ -30,6 +30,7 @@ import { AccessibilityLabel, AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
|
30
30
|
import RenameScript from './Components/RenameScript';
|
|
31
31
|
import DeleteScript from './Components/DeleteScript';
|
|
32
32
|
import Images from '../../../configs/Images';
|
|
33
|
+
import { useBackendPermission } from '../../../utils/Permission/backend';
|
|
33
34
|
|
|
34
35
|
const PreventDoubleTouch = withPreventDoubleClick(TouchableOpacity);
|
|
35
36
|
|
|
@@ -122,9 +123,9 @@ const ScriptDetail = ({ route }) => {
|
|
|
122
123
|
const handleScriptAction = useCallback(async () => {
|
|
123
124
|
const { success } = await axiosPost(API.AUTOMATE.ACTION_ONE_TAP(id));
|
|
124
125
|
if (success) {
|
|
125
|
-
ToastBottomHelper.success(t('
|
|
126
|
+
ToastBottomHelper.success(t('activated_successfully'));
|
|
126
127
|
} else {
|
|
127
|
-
ToastBottomHelper.error(t('
|
|
128
|
+
ToastBottomHelper.error(t('activation_failed'));
|
|
128
129
|
}
|
|
129
130
|
}, [id, t]);
|
|
130
131
|
|
|
@@ -296,9 +297,14 @@ const Item = ({ item, index }) => {
|
|
|
296
297
|
const ItemAdd = ({ automate, index }) => {
|
|
297
298
|
const t = useTranslations();
|
|
298
299
|
const { navigate } = useNavigation();
|
|
300
|
+
const permissions = useBackendPermission();
|
|
299
301
|
const { name: currentScreenName } = useRoute();
|
|
300
302
|
|
|
301
303
|
const onPressAddAction = useCallback(() => {
|
|
304
|
+
if (permissions?.max_actions_per_automation <= index) {
|
|
305
|
+
ToastBottomHelper.error(t('reach_max_actions_per_automation'));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
302
308
|
const navParams = {
|
|
303
309
|
unitId: automate.unit,
|
|
304
310
|
automateId: automate.id,
|
|
@@ -309,7 +315,15 @@ const ItemAdd = ({ automate, index }) => {
|
|
|
309
315
|
automate.unit ? Routes.SelectControlDevices : Routes.SelectUnit,
|
|
310
316
|
navParams
|
|
311
317
|
);
|
|
312
|
-
}, [
|
|
318
|
+
}, [
|
|
319
|
+
permissions?.max_actions_per_automation,
|
|
320
|
+
index,
|
|
321
|
+
automate.unit,
|
|
322
|
+
automate.id,
|
|
323
|
+
currentScreenName,
|
|
324
|
+
navigate,
|
|
325
|
+
t,
|
|
326
|
+
]);
|
|
313
327
|
|
|
314
328
|
return (
|
|
315
329
|
<View style={styles.wrapItem}>
|
|
@@ -15,11 +15,12 @@ import { getTranslate } from '../../../utils/I18n';
|
|
|
15
15
|
import { AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
16
16
|
import api from '../../../utils/Apis/axios';
|
|
17
17
|
import { API } from '../../../configs';
|
|
18
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
18
19
|
|
|
19
20
|
const mock = new MockAdapter(api.axiosInstance);
|
|
20
21
|
|
|
21
|
-
const wrapComponent = () => (
|
|
22
|
-
<SCProvider initState={mockSCStore(
|
|
22
|
+
const wrapComponent = (storeData = {}) => (
|
|
23
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
23
24
|
<MultiUnits />
|
|
24
25
|
</SCProvider>
|
|
25
26
|
);
|
|
@@ -31,6 +32,7 @@ describe('Test MultiUnits', () => {
|
|
|
31
32
|
beforeEach(() => {
|
|
32
33
|
mockedNavigate.mockClear();
|
|
33
34
|
useRoute.mockClear();
|
|
35
|
+
mock.reset();
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
it('Test is multi unit and current is Automation tab', async () => {
|
|
@@ -151,9 +153,7 @@ describe('Test MultiUnits', () => {
|
|
|
151
153
|
mock.onGet(API.AUTOMATE.GET_MULTI_UNITS()).reply(200, response);
|
|
152
154
|
useRoute.mockReturnValue({
|
|
153
155
|
params: {
|
|
154
|
-
|
|
155
|
-
unitName: null,
|
|
156
|
-
unit: null,
|
|
156
|
+
unit: {},
|
|
157
157
|
},
|
|
158
158
|
});
|
|
159
159
|
await act(async () => {
|
|
@@ -180,9 +180,66 @@ describe('Test MultiUnits', () => {
|
|
|
180
180
|
});
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
+
it('create new smart but reach max', async () => {
|
|
184
|
+
const response = [
|
|
185
|
+
{
|
|
186
|
+
id: 1,
|
|
187
|
+
user: 223,
|
|
188
|
+
type: 'one_tap',
|
|
189
|
+
config: null,
|
|
190
|
+
value: null,
|
|
191
|
+
activate_at: '2021-09-22T14:16:54Z',
|
|
192
|
+
condition: null,
|
|
193
|
+
script: {
|
|
194
|
+
id: 1,
|
|
195
|
+
name: 'Tap to up down up down coc coc coc coc coc',
|
|
196
|
+
icon: null,
|
|
197
|
+
icon_kit:
|
|
198
|
+
'https://eoh-gateway-backend.eoh.io/_Category_Sensors_Type_Garage_door_StyleC_olorful.png',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
mock.onGet(API.UNIT.AUTOMATE(1)).reply(200, response);
|
|
203
|
+
useRoute.mockReturnValue({
|
|
204
|
+
params: {
|
|
205
|
+
unit: { id: 1 },
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
await act(async () => {
|
|
209
|
+
tree = await create(
|
|
210
|
+
wrapComponent({
|
|
211
|
+
auth: {
|
|
212
|
+
account: {
|
|
213
|
+
user: {
|
|
214
|
+
permissions: {
|
|
215
|
+
max_automations_per_unit: 0,
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
const instance = tree.root;
|
|
224
|
+
const itemAddNews = instance.findAllByType(ItemAddNew);
|
|
225
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
226
|
+
await act(async () => {
|
|
227
|
+
itemAddNews[0].props.onAddNew();
|
|
228
|
+
});
|
|
229
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
230
|
+
expect(spyToastError).toBeCalledWith(
|
|
231
|
+
getTranslate('en', 'reach_max_automations_per_unit')
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
|
|
183
235
|
it('Test is not multi unit', async () => {
|
|
184
236
|
useRoute.mockReturnValue({
|
|
185
|
-
params: {
|
|
237
|
+
params: {
|
|
238
|
+
unit: {
|
|
239
|
+
id: 1,
|
|
240
|
+
name: '',
|
|
241
|
+
},
|
|
242
|
+
},
|
|
186
243
|
});
|
|
187
244
|
await act(async () => {
|
|
188
245
|
tree = await create(wrapComponent());
|
|
@@ -13,11 +13,13 @@ import { AccessibilityLabel } from '../../../configs/Constants';
|
|
|
13
13
|
import api from '../../../utils/Apis/axios';
|
|
14
14
|
import { API } from '../../../configs';
|
|
15
15
|
import { useNavigation } from '@react-navigation/native';
|
|
16
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
17
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
16
18
|
|
|
17
19
|
const mock = new MockAdapter(api.axiosInstance);
|
|
18
20
|
|
|
19
|
-
const wrapComponent = () => (
|
|
20
|
-
<SCProvider initState={mockSCStore(
|
|
21
|
+
const wrapComponent = (storeData = {}) => (
|
|
22
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
21
23
|
<Automate />
|
|
22
24
|
</SCProvider>
|
|
23
25
|
);
|
|
@@ -100,6 +102,44 @@ describe('Test Automate', () => {
|
|
|
100
102
|
});
|
|
101
103
|
});
|
|
102
104
|
|
|
105
|
+
it('onPress onAddNew but reach limit', async () => {
|
|
106
|
+
mock.onGet(API.AUTOMATE.GET_SMART()).reply(200, [
|
|
107
|
+
{
|
|
108
|
+
type: 'MultiUnit',
|
|
109
|
+
unit_id: 1,
|
|
110
|
+
automates: [],
|
|
111
|
+
},
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
await act(async () => {
|
|
115
|
+
tree = await create(
|
|
116
|
+
wrapComponent({
|
|
117
|
+
auth: {
|
|
118
|
+
account: {
|
|
119
|
+
user: {
|
|
120
|
+
permissions: {
|
|
121
|
+
max_automations_per_unit: 0,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
})
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const instance = tree.root;
|
|
131
|
+
|
|
132
|
+
const itemAddNew = instance.findByType(ItemAddNew);
|
|
133
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
134
|
+
await act(async () => {
|
|
135
|
+
itemAddNew.props.onAddNew(1, []);
|
|
136
|
+
});
|
|
137
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
138
|
+
expect(spyToastError).toBeCalledWith(
|
|
139
|
+
getTranslate('en', 'reach_max_automations_per_unit')
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
103
143
|
it('Test success get Automate onPressItem to ScriptDetail', async () => {
|
|
104
144
|
const response = {
|
|
105
145
|
status: 200,
|
|
@@ -193,10 +233,7 @@ describe('Test Automate', () => {
|
|
|
193
233
|
});
|
|
194
234
|
|
|
195
235
|
expect(mockedNavigate).toBeCalledWith(Routes.MultiUnits, {
|
|
196
|
-
|
|
197
|
-
unitName: '',
|
|
198
|
-
unit: { id: undefined },
|
|
199
|
-
isOwner: true,
|
|
236
|
+
unit: { id: undefined, name: '' },
|
|
200
237
|
});
|
|
201
238
|
|
|
202
239
|
mockedNavigate.mockClear();
|
|
@@ -205,10 +242,7 @@ describe('Test Automate', () => {
|
|
|
205
242
|
});
|
|
206
243
|
|
|
207
244
|
expect(mockedNavigate).toBeCalledWith(Routes.MultiUnits, {
|
|
208
|
-
|
|
209
|
-
unitName: 'La Vida',
|
|
210
|
-
unit: { id: 3 },
|
|
211
|
-
isOwner: false,
|
|
245
|
+
unit: { id: 3, name: 'La Vida' },
|
|
212
246
|
});
|
|
213
247
|
});
|
|
214
248
|
});
|