@eohjsc/react-native-smart-city 0.3.93 → 0.3.95

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 (48) hide show
  1. package/package.json +1 -1
  2. package/src/commons/ActionGroup/OnOffTemplate/index.js +20 -17
  3. package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +1 -1
  4. package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +5 -24
  5. package/src/commons/SubUnit/OneTap/ItemOneTap.js +83 -85
  6. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +68 -24
  7. package/src/commons/SubUnit/OneTap/index.js +21 -1
  8. package/src/configs/API.js +1 -0
  9. package/src/screens/ActivityLog/__test__/index.test.js +60 -2
  10. package/src/screens/ActivityLog/hooks/__test__/index.test.js +5 -0
  11. package/src/screens/ActivityLog/hooks/index.js +11 -0
  12. package/src/screens/AddLocationMaps/index.js +1 -1
  13. package/src/screens/AddNewGateway/ConnectingDevice.js +7 -0
  14. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +6 -4
  15. package/src/screens/AddNewGateway/ConnectingWifiGuide.js +0 -1
  16. package/src/screens/AddNewGateway/RenameNewDevices.js +2 -2
  17. package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +1 -6
  18. package/src/screens/AddNewGateway/SelectDeviceType.js +67 -9
  19. package/src/screens/AddNewGateway/ShareWifiPassword.js +20 -3
  20. package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +35 -0
  21. package/src/screens/AddNewGateway/__test__/ScanWifiDeviceQR.test.js +0 -10
  22. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +183 -29
  23. package/src/screens/AllGateway/GatewayInfo/index.js +3 -3
  24. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +0 -1
  25. package/src/screens/Automate/MultiUnits.js +32 -18
  26. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +36 -2
  27. package/src/screens/Automate/ScriptDetail/index.js +17 -3
  28. package/src/screens/Automate/Styles/MultiUnitsStyles.js +1 -1
  29. package/src/screens/Automate/__test__/MultiUnits.test.js +125 -8
  30. package/src/screens/Automate/__test__/index.test.js +95 -11
  31. package/src/screens/Automate/index.js +62 -38
  32. package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +24 -1
  33. package/src/screens/Sharing/InfoMemberUnit.js +2 -2
  34. package/src/screens/Sharing/MemberList.js +28 -7
  35. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +32 -18
  36. package/src/screens/Sharing/__test__/MemberList.test.js +37 -4
  37. package/src/screens/SubUnit/AddSubUnit.js +1 -1
  38. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +16 -3
  39. package/src/screens/Unit/AddMenu.js +42 -19
  40. package/src/screens/Unit/__test__/AddMenu.test.js +68 -15
  41. package/src/screens/Unit/components/AutomateScript/index.js +1 -1
  42. package/src/utils/I18n/translations/en.js +1409 -0
  43. package/src/utils/I18n/translations/vi.js +1414 -0
  44. package/src/utils/I18n/translations.ts +2 -2
  45. package/src/utils/Permission/backend.js +7 -0
  46. package/src/screens/Sharing/__test__/MemberList2.test.js +0 -74
  47. package/src/utils/I18n/translations/en.json +0 -1142
  48. package/src/utils/I18n/translations/vi.json +0 -1139
@@ -81,6 +81,13 @@ const ConnectingDevice = ({
81
81
  if (found) {
82
82
  return { ...oldParams };
83
83
  }
84
+ if (data?.type === 'rejoin') {
85
+ return {
86
+ ...oldParams,
87
+ isRejoin: true,
88
+ sensorId: data?.sensor?.id,
89
+ };
90
+ }
84
91
  return oldParams;
85
92
  });
86
93
  },
@@ -12,7 +12,7 @@ let isCallingAPI = false;
12
12
 
13
13
  const ConnectingWifiDevice = ({ route }) => {
14
14
  const t = useTranslations();
15
- const { unit, subUnit, gateway, selectedWifi, qrData, addDeviceType } =
15
+ const { unit, subUnit, gateway, selectedWifi, qrData, addDeviceType, code } =
16
16
  route?.params || {};
17
17
  const { goBack } = useNavigation();
18
18
 
@@ -40,7 +40,8 @@ const ConnectingWifiDevice = ({ route }) => {
40
40
  const { success, problem, data } = await axiosPost(
41
41
  API.UNIT.CHIP_SCAN(unit?.id),
42
42
  {
43
- imei: gateway?.imei,
43
+ code,
44
+ host: qrData?.host,
44
45
  secret: qrData?.secret,
45
46
  name: gateway?.model,
46
47
  station: subUnit?.id,
@@ -61,9 +62,10 @@ const ConnectingWifiDevice = ({ route }) => {
61
62
  },
62
63
  [
63
64
  unit?.id,
64
- gateway?.imei,
65
- gateway?.model,
65
+ code,
66
+ qrData?.host,
66
67
  qrData?.secret,
68
+ gateway?.model,
67
69
  subUnit?.id,
68
70
  selectedWifi.ssid,
69
71
  selectedWifi.password,
@@ -124,7 +124,6 @@ const ConnectingWifiGuide = ({ route }) => {
124
124
  socket = dgram.createSocket({ type: 'udp4' });
125
125
  socket.bind(54321);
126
126
  }
127
-
128
127
  socket.on('message', (msg, rinfo) => {
129
128
  const data = JSON.parse(msg.toString());
130
129
  if (Object.prototype.hasOwnProperty.call(data, 'wifi')) {
@@ -21,7 +21,7 @@ const RenameNewDevices = memo(({ route }) => {
21
21
  const t = useTranslations();
22
22
  const { dispatch } = useNavigation();
23
23
 
24
- const { unit, subUnit, chipId, sensorId, addDeviceType } =
24
+ const { unit, subUnit, chipId, sensorId, addDeviceType, isRejoin } =
25
25
  route?.params || {};
26
26
  const [selectedItem, setSelectedItem] = useState({});
27
27
  const [isCanRename, setIsCanRename] = useState(false);
@@ -268,7 +268,7 @@ const RenameNewDevices = memo(({ route }) => {
268
268
  size={20}
269
269
  style={styles.textStatus}
270
270
  >
271
- {t('successfully_connected')}
271
+ {t(`successfully_${isRejoin ? 'rejoined' : 'connected'}`)}
272
272
  </Text>
273
273
  <Text size={14} color={Colors.Gray9}>
274
274
  {[unit?.name, subUnit?.name].filter(Boolean).join(' - ')}
@@ -9,7 +9,6 @@ const ScanWifiDeviceQR = memo(({ route }) => {
9
9
  const { unit, subUnit } = route?.params || {};
10
10
  const [isInvalidQrCode, setIsInvalidQrCode] = useState(false);
11
11
  const { navigate, goBack } = useNavigation();
12
-
13
12
  const onScan = useCallback(
14
13
  (body, setLoading) => {
15
14
  let data;
@@ -20,11 +19,7 @@ const ScanWifiDeviceQR = memo(({ route }) => {
20
19
  setLoading(false);
21
20
  return;
22
21
  }
23
- if (data?.prefix !== 'robot') {
24
- setIsInvalidQrCode(true);
25
- setLoading(false);
26
- return;
27
- }
22
+
28
23
  navigate(Routes.ConnectingWifiGuide, {
29
24
  unit,
30
25
  subUnit,
@@ -14,13 +14,19 @@ import AddZigbeeDeviceIcon from '../../../assets/images/AddNewDevice/add-zigbee-
14
14
  import styles from './SelectDeviceTypeStyles';
15
15
  import AccessibilityLabel from '../../configs/AccessibilityLabel';
16
16
  import { DEVICE_TYPE } from '../../configs/Constants';
17
+ import { useBackendPermission } from '../../utils/Permission/backend';
18
+ import { axiosGet } from '../../utils/Apis/axios';
19
+ import API from '../../configs/API';
20
+ import { ToastBottomHelper } from '../../utils/Utils';
17
21
 
18
22
  const SelectDeviceGrid = ({ options, onSelect }) => {
19
23
  const [selectIndexes, setSelectIndexes] = useState();
20
24
  const onSelectOption = useCallback(
21
25
  (value) => () => {
26
+ if (onSelect(value) === false) {
27
+ return;
28
+ }
22
29
  setSelectIndexes(value);
23
- onSelect(value);
24
30
  },
25
31
  [onSelect]
26
32
  );
@@ -51,17 +57,33 @@ const SelectDeviceGrid = ({ options, onSelect }) => {
51
57
  );
52
58
  };
53
59
 
60
+ const getPermissionCode = (deviceType) => {
61
+ switch (deviceType) {
62
+ case 'gateway_qr':
63
+ return 'plug_and_play_gateway';
64
+ case 'wifi_device_qr':
65
+ return 'plug_and_play_wifi';
66
+ case 'modbus_device_qr':
67
+ return 'plug_and_play_modbus';
68
+ case 'zigbee':
69
+ default:
70
+ return 'plug_and_play_zigbee';
71
+ }
72
+ };
73
+
54
74
  const SelectDeviceType = ({ route }) => {
55
75
  const t = useTranslations();
56
76
  const { unit, subUnit } = route?.params || {};
57
77
  const { navigate, goBack } = useNavigation();
78
+ const [unitCountSummary, setUnitCountSummary] = useState();
58
79
  const [addType, setAddType] = useState();
59
80
  const [selectedAddType, setSelectedAddType] = useState();
81
+ const permissions = useBackendPermission();
60
82
 
61
83
  const listDeviceType = useMemo(() => {
62
84
  const list = [
63
85
  {
64
- id: 1,
86
+ id: 'gateway_qr',
65
87
  image: <AddGatewayIcon width={60} height={60} />,
66
88
  route: Routes.ScanGatewayQR,
67
89
  data: {
@@ -71,7 +93,7 @@ const SelectDeviceType = ({ route }) => {
71
93
  subtitle: t('central_controller'),
72
94
  },
73
95
  {
74
- id: 2,
96
+ id: 'wifi_device_qr',
75
97
  image: <AddWifiDeviceIcon width={60} height={60} />,
76
98
  route: subUnit?.id
77
99
  ? Routes.ScanWifiDeviceQR
@@ -85,7 +107,7 @@ const SelectDeviceType = ({ route }) => {
85
107
  subtitle: t('device_connect_without_gateway'),
86
108
  },
87
109
  {
88
- id: 3,
110
+ id: 'modbus_device_qr',
89
111
  image: <AddModbusDeviceIcon width={60} height={60} />,
90
112
  route: subUnit?.id ? Routes.ScanModbusQR : Routes.SelectDeviceSubUnit,
91
113
  data: {
@@ -97,7 +119,7 @@ const SelectDeviceType = ({ route }) => {
97
119
  subtitle: t('device_connect_directly_to_the_gateway'),
98
120
  },
99
121
  {
100
- id: 4,
122
+ id: 'zigbee',
101
123
  image: <AddZigbeeDeviceIcon width={60} height={60} />,
102
124
  route: subUnit?.id
103
125
  ? Routes.ConnectRouterGuide
@@ -111,19 +133,43 @@ const SelectDeviceType = ({ route }) => {
111
133
  subtitle: t('device_connect_remotely_to_the_gateway'),
112
134
  },
113
135
  ];
114
- if (!!subUnit?.id) {
136
+ if (subUnit?.id) {
115
137
  list.shift();
116
138
  }
117
139
  return list;
118
140
  }, [unit, t, subUnit]);
119
141
 
120
142
  const onRight = useCallback(() => {
121
- if (selectedAddType?.route && selectedAddType?.data) {
122
- navigate(selectedAddType?.route, selectedAddType?.data);
143
+ if (!selectedAddType?.route) {
144
+ return;
123
145
  }
146
+
147
+ navigate(selectedAddType?.route, selectedAddType?.data);
124
148
  }, [navigate, selectedAddType?.data, selectedAddType?.route]);
125
149
 
126
150
  const handleOnSelect = (itemSelect) => {
151
+ const needPermission = getPermissionCode(itemSelect);
152
+ if (!permissions?.[needPermission]) {
153
+ ToastBottomHelper.error(t(`no_permission_${needPermission}`));
154
+ return false;
155
+ }
156
+
157
+ if (['gateway_qr', 'wifi_device_qr'].includes(itemSelect)) {
158
+ if (permissions?.max_chips_per_unit <= unitCountSummary?.total_chips) {
159
+ ToastBottomHelper.error(t('reach_max_chips_per_unit'));
160
+ return false;
161
+ }
162
+ }
163
+
164
+ if (['wifi_device_qr', 'modbus_device_qr', 'zigbee'].includes(itemSelect)) {
165
+ if (
166
+ permissions?.max_configs_per_unit <= unitCountSummary?.total_configs
167
+ ) {
168
+ ToastBottomHelper.error(t('reach_max_configs_per_unit'));
169
+ return false;
170
+ }
171
+ }
172
+
127
173
  setAddType(itemSelect);
128
174
  };
129
175
 
@@ -131,6 +177,18 @@ const SelectDeviceType = ({ route }) => {
131
177
  setSelectedAddType(listDeviceType.find((item) => item.id === addType));
132
178
  }, [addType, listDeviceType]);
133
179
 
180
+ useEffect(() => {
181
+ const fetchCountSummary = async () => {
182
+ const { success, data } = await axiosGet(API.DEV_MODE.GATEWAY.COUNT(), {
183
+ unit: unit?.id,
184
+ });
185
+ if (success) {
186
+ setUnitCountSummary(data);
187
+ }
188
+ };
189
+ fetchCountSummary();
190
+ }, [unit?.id]);
191
+
134
192
  return (
135
193
  <View style={styles.container}>
136
194
  <HeaderCustom title={t('choose_type_of_device')} isShowSeparator />
@@ -141,7 +199,7 @@ const SelectDeviceType = ({ route }) => {
141
199
  leftTitle={t('cancel')}
142
200
  onLeftClick={goBack}
143
201
  rightTitle={t('text_next')}
144
- rightDisabled={!addType}
202
+ rightDisabled={!unitCountSummary || !addType}
145
203
  onRightClick={onRight}
146
204
  />
147
205
  </View>
@@ -1,4 +1,10 @@
1
- import React, { useCallback, useRef, useState, useEffect } from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useRef,
4
+ useState,
5
+ useEffect,
6
+ useMemo,
7
+ } from 'react';
2
8
  import {
3
9
  Alert,
4
10
  TouchableOpacity,
@@ -9,6 +15,7 @@ import {
9
15
  import dgram from 'react-native-udp';
10
16
  import { useNavigation, useIsFocused } from '@react-navigation/native';
11
17
  import LottieView from 'lottie-react-native';
18
+ import uuid from 'uuid';
12
19
 
13
20
  import { ToastBottomHelper } from '../../utils/Utils';
14
21
  import { useTranslations } from '../../hooks/Common/useTranslations';
@@ -68,6 +75,10 @@ const ShareWifiPassword = ({ route }) => {
68
75
  const [isDisabled, setIsDisabled] = useState(false);
69
76
  const [dataGateway, setDataGateway] = useState({ gateway: [], error: '' });
70
77
 
78
+ const code = useMemo(() => {
79
+ return uuid.v4();
80
+ }, []);
81
+
71
82
  const hidePopupPassword = useCallback(() => {
72
83
  setIsShowPopupPassword(false);
73
84
  }, []);
@@ -80,7 +91,11 @@ const ShareWifiPassword = ({ route }) => {
80
91
  socket.send(
81
92
  JSON.stringify({
82
93
  type: 'connect',
83
- data: { wifi: { ssid: selectedWifi, pass: selectedWifiPassword } },
94
+ data: {
95
+ token: code,
96
+ host: qrData?.host,
97
+ wifi: { ssid: selectedWifi, pass: selectedWifiPassword },
98
+ },
84
99
  }),
85
100
  undefined,
86
101
  undefined,
@@ -94,7 +109,7 @@ const ShareWifiPassword = ({ route }) => {
94
109
  }
95
110
  }, 1000);
96
111
  },
97
- [selectedWifiPassword, selectedWifi]
112
+ [code, qrData?.host, selectedWifi, selectedWifiPassword]
98
113
  );
99
114
 
100
115
  const isWrongPassword = useRef(true);
@@ -197,6 +212,7 @@ const ShareWifiPassword = ({ route }) => {
197
212
  password: selectedWifiPassword,
198
213
  },
199
214
  addDeviceType,
215
+ code,
200
216
  });
201
217
  }
202
218
  }, 800);
@@ -223,6 +239,7 @@ const ShareWifiPassword = ({ route }) => {
223
239
  t,
224
240
  wifiList,
225
241
  unit,
242
+ code,
226
243
  ]);
227
244
 
228
245
  return (
@@ -121,4 +121,39 @@ describe('Test connecting modbus device', () => {
121
121
  sensorId: 1,
122
122
  });
123
123
  });
124
+
125
+ it('receive sensor from channel after rejoin zigbee', async () => {
126
+ mock.onPost().reply(200, {});
127
+ await act(async () => {
128
+ tree = await create(wrapComponent(route));
129
+ });
130
+ const channels = getPusher().channels;
131
+ let channel;
132
+ for (const key in channels) {
133
+ if (key.indexOf('cache-') === 0) {
134
+ channel = channels[key];
135
+ }
136
+ }
137
+ await act(async () => {
138
+ await channel.trigger('progress', {
139
+ data: { sensor: { id: 1, name: 'sensor' }, type: 'rejoin' },
140
+ });
141
+ });
142
+ await act(async () => {
143
+ await channel.trigger('progress', { success: 1 });
144
+ });
145
+ expect(mockedNavigate).toHaveBeenCalledWith(Routes.RenameNewDevices, {
146
+ addDeviceType: undefined,
147
+ unit: {
148
+ id: 1,
149
+ },
150
+ subUnit: {
151
+ id: 2,
152
+ station: 'Station 2',
153
+ },
154
+ chipId: 3,
155
+ sensorId: 1,
156
+ isRejoin: true,
157
+ });
158
+ });
124
159
  });
@@ -5,7 +5,6 @@ import ScanWifiDeviceQR from '../ScanWifiDeviceQR';
5
5
  import { SCProvider } from '../../../context';
6
6
  import { mockSCStore } from '../../../context/mockStore';
7
7
  import QRScan from '../../ScanChipQR/components/QRScan';
8
- import { getTranslate } from '../../../utils/I18n';
9
8
  import Routes from '../../../utils/Route';
10
9
 
11
10
  const mockedGoBack = jest.fn();
@@ -54,15 +53,6 @@ describe('test scan wifi device QR', () => {
54
53
  });
55
54
  };
56
55
 
57
- it('on scan wrong QR code', async () => {
58
- await scanQRCode({ imei: 'SAMSUNG-xxx' });
59
- const instance = tree.root;
60
- const bottomSheet = instance.findByProps({
61
- title: getTranslate('en', 'invalid_qr_code'),
62
- });
63
- expect(bottomSheet.props.isVisible).toBe(true);
64
- });
65
-
66
56
  it('on scan correct QR code', async () => {
67
57
  await scanQRCode({ prefix: 'robot', org_slug: 'eoh' }, jest.fn());
68
58
  expect(mockedNavigate).toHaveBeenCalled();
@@ -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
- const wrapComponent = (route) => (
13
- <SCProvider initState={mockSCStore({})}>
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 mockedNavigate = jest.fn();
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
- afterEach(() => {
37
- mockedNavigate.mockClear();
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(0);
108
- expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.ScanGatewayQR);
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(1);
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(2);
116
- expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
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(3);
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
  });
@@ -36,7 +36,7 @@ const GatewayInfo = () => {
36
36
  date_install = '',
37
37
  expired_at = '',
38
38
  firmware = {},
39
- imei = '',
39
+ code = '',
40
40
  arduino_gateway = undefined,
41
41
  modbus_gateway = undefined,
42
42
  zigbee_gateway = undefined,
@@ -81,7 +81,7 @@ const GatewayInfo = () => {
81
81
  {
82
82
  id: 5,
83
83
  title: 'auth_token',
84
- data: imei || '--',
84
+ data: code || '--',
85
85
  },
86
86
  {
87
87
  id: 7,
@@ -105,7 +105,7 @@ const GatewayInfo = () => {
105
105
  expired_at,
106
106
  firmware?.board,
107
107
  id,
108
- imei,
108
+ code,
109
109
  wifi_ssid,
110
110
  ]
111
111
  );
@@ -172,7 +172,6 @@ const SetupConfigCondition = () => {
172
172
  style={styles.modal}
173
173
  >
174
174
  <View style={styles.modalContent}>
175
- <Text type="H3">{t('select_condition')}</Text>
176
175
  {conditionOptions.map((option, index) => (
177
176
  <React.Fragment key={index}>
178
177
  <TouchableOpacity