@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.
- package/package.json +1 -1
- package/src/commons/ActionGroup/OnOffTemplate/index.js +20 -17
- package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +5 -24
- 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/ActivityLog/__test__/index.test.js +60 -2
- package/src/screens/ActivityLog/hooks/__test__/index.test.js +5 -0
- package/src/screens/ActivityLog/hooks/index.js +11 -0
- package/src/screens/AddLocationMaps/index.js +1 -1
- package/src/screens/AddNewGateway/ConnectingDevice.js +7 -0
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +6 -4
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +0 -1
- package/src/screens/AddNewGateway/RenameNewDevices.js +2 -2
- package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +1 -6
- package/src/screens/AddNewGateway/SelectDeviceType.js +67 -9
- package/src/screens/AddNewGateway/ShareWifiPassword.js +20 -3
- package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +35 -0
- package/src/screens/AddNewGateway/__test__/ScanWifiDeviceQR.test.js +0 -10
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +183 -29
- package/src/screens/AllGateway/GatewayInfo/index.js +3 -3
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +0 -1
- package/src/screens/Automate/MultiUnits.js +32 -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 +125 -8
- package/src/screens/Automate/__test__/index.test.js +95 -11
- package/src/screens/Automate/index.js +62 -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/SubUnit/AddSubUnit.js +1 -1
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +16 -3
- 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 +1414 -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
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { renderHook } from '@testing-library/react-hooks';
|
|
3
|
-
import { useEvaluateValue } from '../useEvaluateValue';
|
|
3
|
+
import { useEvaluateValue, useGetEvaluateValue } from '../useEvaluateValue';
|
|
4
4
|
import { SCProvider } from '../../../../context';
|
|
5
5
|
import { mockSCStore } from '../../../../context/mockStore';
|
|
6
|
+
import { API } from '../../../../configs';
|
|
7
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
8
|
+
import api from '../../../../utils/Apis/axios';
|
|
9
|
+
import { flushPromises } from '../../../AllGateway/test-utils';
|
|
6
10
|
|
|
7
11
|
const wrapper =
|
|
8
12
|
(valueEvaluations) =>
|
|
@@ -99,4 +103,23 @@ describe('Test useEvaluateValue', () => {
|
|
|
99
103
|
expect(evaluateValue.current(2, 1).text).toBe('On');
|
|
100
104
|
expect(evaluateValue.current(2, 2).text).toBe(2);
|
|
101
105
|
});
|
|
106
|
+
|
|
107
|
+
it('test evaluate fetch from server if not exists', async () => {
|
|
108
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
109
|
+
mock.onGet(API.FETCH_VALUE_EVALUATION(111)).reply(200, {
|
|
110
|
+
unit_id: 1,
|
|
111
|
+
configs: [111],
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const { result: evaluateValue } = renderHook(
|
|
115
|
+
() => useGetEvaluateValue(111),
|
|
116
|
+
{
|
|
117
|
+
wrapper: wrapper(valueEvaluations),
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
expect(evaluateValue.current).toBe(undefined);
|
|
121
|
+
await flushPromises();
|
|
122
|
+
|
|
123
|
+
expect(mock.history.get.length).toBe(1);
|
|
124
|
+
});
|
|
102
125
|
});
|
|
@@ -148,9 +148,10 @@ const InfoMemberUnit = memo(({ route }) => {
|
|
|
148
148
|
stateAlertAction?.is_change,
|
|
149
149
|
stateAlertAction?.message,
|
|
150
150
|
]);
|
|
151
|
+
|
|
151
152
|
const handleShareDevice = useCallback(() => {
|
|
152
153
|
if (isOwner && memberInfo?.identity === 'member') {
|
|
153
|
-
|
|
154
|
+
navigate(Routes.AddMemberStack, {
|
|
154
155
|
screen: Routes.SharingSelectPermission,
|
|
155
156
|
params: {
|
|
156
157
|
unit: { id: unit?.id },
|
|
@@ -159,7 +160,6 @@ const InfoMemberUnit = memo(({ route }) => {
|
|
|
159
160
|
},
|
|
160
161
|
});
|
|
161
162
|
}
|
|
162
|
-
return <></>;
|
|
163
163
|
}, [isOwner, navigate, unit?.id, memberInfo]);
|
|
164
164
|
|
|
165
165
|
const footerWarning = useMemo(() => {
|
|
@@ -14,6 +14,8 @@ import AlertAction from '../../commons/AlertAction';
|
|
|
14
14
|
import { useDataMember, useStateAlertAction } from './hooks';
|
|
15
15
|
import { AccessibilityLabel } from '../../configs/Constants';
|
|
16
16
|
import { useSCContextSelector } from '../../context';
|
|
17
|
+
import { useBackendPermission } from '../../utils/Permission/backend';
|
|
18
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
17
19
|
|
|
18
20
|
const MemberList = ({ route }) => {
|
|
19
21
|
const t = useTranslations();
|
|
@@ -24,20 +26,39 @@ const MemberList = ({ route }) => {
|
|
|
24
26
|
const { dataMembers, isRefresh, onRefresh, leaveUnit, loading } =
|
|
25
27
|
useDataMember(unitId, unit?.user_id);
|
|
26
28
|
const { isOwner } = useIsOwnerOfUnit(unit?.user_id);
|
|
29
|
+
const permissions = useBackendPermission();
|
|
27
30
|
|
|
28
31
|
const { stateAlertSharingMenu, hideStateAlertSharingMenu, stateLeaveUnit } =
|
|
29
32
|
useStateAlertAction();
|
|
30
33
|
|
|
31
34
|
const onPressRightHeader = useCallback(() => {
|
|
32
|
-
if (isOwner) {
|
|
33
|
-
navigate(Routes.AddMemberStack, {
|
|
34
|
-
screen: Routes.SharingSelectPermission,
|
|
35
|
-
params: { unit: { id: unitId } },
|
|
36
|
-
});
|
|
37
|
-
} else {
|
|
35
|
+
if (!isOwner) {
|
|
38
36
|
stateLeaveUnit(); //change state stateAlertAction
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (permissions?.max_members_per_unit <= dataMembers.length) {
|
|
41
|
+
ToastBottomHelper.error(
|
|
42
|
+
t('reach_max_members_per_unit', {
|
|
43
|
+
max: permissions?.max_members_per_unit,
|
|
44
|
+
})
|
|
45
|
+
);
|
|
46
|
+
return;
|
|
39
47
|
}
|
|
40
|
-
|
|
48
|
+
|
|
49
|
+
navigate(Routes.AddMemberStack, {
|
|
50
|
+
screen: Routes.SharingSelectPermission,
|
|
51
|
+
params: { unit: { id: unitId } },
|
|
52
|
+
});
|
|
53
|
+
}, [
|
|
54
|
+
dataMembers.length,
|
|
55
|
+
isOwner,
|
|
56
|
+
navigate,
|
|
57
|
+
permissions?.max_members_per_unit,
|
|
58
|
+
stateLeaveUnit,
|
|
59
|
+
t,
|
|
60
|
+
unitId,
|
|
61
|
+
]);
|
|
41
62
|
|
|
42
63
|
const handleLeave = useCallback(() => {
|
|
43
64
|
if (!isOwner) {
|
|
@@ -14,6 +14,7 @@ import api from '../../../utils/Apis/axios';
|
|
|
14
14
|
import ItemChangeRole from '../Components/ItemChangeRole';
|
|
15
15
|
import ModalPopupCT from '../../../commons/ModalPopupCT';
|
|
16
16
|
import Routes from '../../../utils/Route';
|
|
17
|
+
import { useNavigation } from '@react-navigation/native';
|
|
17
18
|
|
|
18
19
|
const mock = new MockAdapter(api.axiosInstance);
|
|
19
20
|
|
|
@@ -22,22 +23,6 @@ jest.mock('../../../hooks/Common', () => {
|
|
|
22
23
|
useIsOwnerOfUnit: () => ({ isOwner: true }),
|
|
23
24
|
};
|
|
24
25
|
});
|
|
25
|
-
const mockUseIsFocused = jest.fn();
|
|
26
|
-
const mockedNavigate = jest.fn();
|
|
27
|
-
|
|
28
|
-
const mockGoBack = jest.fn();
|
|
29
|
-
|
|
30
|
-
jest.mock('@react-navigation/native', () => {
|
|
31
|
-
return {
|
|
32
|
-
...jest.requireActual('@react-navigation/native'),
|
|
33
|
-
useRoute: jest.fn(),
|
|
34
|
-
useNavigation: () => ({
|
|
35
|
-
goBack: mockGoBack,
|
|
36
|
-
navigate: mockedNavigate,
|
|
37
|
-
}),
|
|
38
|
-
useIsFocused: () => mockUseIsFocused,
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
26
|
|
|
42
27
|
const wrapComponent = (route) => (
|
|
43
28
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -48,9 +33,13 @@ const wrapComponent = (route) => (
|
|
|
48
33
|
describe('Test InfoMemberUnit', () => {
|
|
49
34
|
let tree;
|
|
50
35
|
let route;
|
|
36
|
+
const mockedNavigate = useNavigation().navigate;
|
|
37
|
+
const mockGoBack = useNavigation().goBack;
|
|
51
38
|
|
|
52
39
|
beforeEach(() => {
|
|
53
40
|
mockedNavigate.mockClear();
|
|
41
|
+
mockGoBack.mockClear();
|
|
42
|
+
mock.reset();
|
|
54
43
|
route = {
|
|
55
44
|
params: {
|
|
56
45
|
unit: {
|
|
@@ -112,7 +101,7 @@ describe('Test InfoMemberUnit', () => {
|
|
|
112
101
|
it('render InfoMemberUnit delete member', async () => {
|
|
113
102
|
mock.onGet(API.SHARE.UNIT_MEMBER_INFO(1, 1)).reply(200, {
|
|
114
103
|
id: 2,
|
|
115
|
-
identity: '
|
|
104
|
+
identity: 'member',
|
|
116
105
|
phone_number: '88888',
|
|
117
106
|
name: 'user',
|
|
118
107
|
email: 'abc@gmail.com',
|
|
@@ -130,10 +119,15 @@ describe('Test InfoMemberUnit', () => {
|
|
|
130
119
|
expect(header).toHaveLength(1);
|
|
131
120
|
expect(buttonRemove).toHaveLength(1);
|
|
132
121
|
mock.onDelete(API.SHARE.UNITS_MEMBER_DETAIL(1)).reply(200);
|
|
122
|
+
|
|
123
|
+
const alert = instance.findByType(AlertAction);
|
|
124
|
+
expect(alert.props.visible).toBeFalsy();
|
|
125
|
+
|
|
133
126
|
await act(async () => {
|
|
134
127
|
buttonRemove[0].props.onPress();
|
|
135
128
|
});
|
|
136
|
-
|
|
129
|
+
|
|
130
|
+
expect(alert.props.visible).toBeTruthy();
|
|
137
131
|
});
|
|
138
132
|
|
|
139
133
|
it('test change owner', async () => {
|
|
@@ -191,4 +185,24 @@ describe('Test InfoMemberUnit', () => {
|
|
|
191
185
|
type: 'infoMemberUnit',
|
|
192
186
|
});
|
|
193
187
|
});
|
|
188
|
+
|
|
189
|
+
it('test share device', async () => {
|
|
190
|
+
mock.onGet(API.SHARE.UNIT_MEMBER_INFO(1, 1)).reply(200, {
|
|
191
|
+
id: 2,
|
|
192
|
+
identity: 'member',
|
|
193
|
+
phone_number: '88888',
|
|
194
|
+
name: 'user',
|
|
195
|
+
email: 'abc@gmail.com',
|
|
196
|
+
});
|
|
197
|
+
await act(async () => {
|
|
198
|
+
tree = await create(wrapComponent(route));
|
|
199
|
+
});
|
|
200
|
+
const instance = tree.root;
|
|
201
|
+
const rows = instance.findAllByType(TouchableOpacity);
|
|
202
|
+
|
|
203
|
+
await act(async () => {
|
|
204
|
+
await rows[rows.length - 1].props.onPress();
|
|
205
|
+
});
|
|
206
|
+
expect(mockedNavigate).toBeCalled();
|
|
207
|
+
});
|
|
194
208
|
});
|
|
@@ -10,6 +10,8 @@ import Routes from '../../../utils/Route';
|
|
|
10
10
|
import MockAdapter from 'axios-mock-adapter';
|
|
11
11
|
import api from '../../../utils/Apis/axios';
|
|
12
12
|
import { useNavigation } from '@react-navigation/native';
|
|
13
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
14
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
13
15
|
|
|
14
16
|
new MockAdapter(api.axiosInstance);
|
|
15
17
|
|
|
@@ -19,8 +21,8 @@ jest.mock('../../../hooks/Common', () => {
|
|
|
19
21
|
};
|
|
20
22
|
});
|
|
21
23
|
|
|
22
|
-
const wrapComponent = (route, state) => (
|
|
23
|
-
<SCProvider initState={mockSCStore(
|
|
24
|
+
const wrapComponent = (route, state = {}) => (
|
|
25
|
+
<SCProvider initState={mockSCStore(state)}>
|
|
24
26
|
<MemberList route={route} />
|
|
25
27
|
</SCProvider>
|
|
26
28
|
);
|
|
@@ -64,11 +66,42 @@ describe('test MemberList', () => {
|
|
|
64
66
|
await act(async () => {
|
|
65
67
|
alertAction.props.rightButtonClick();
|
|
66
68
|
});
|
|
67
|
-
const
|
|
68
|
-
await
|
|
69
|
+
const memberListButtons = instance.findAllByType(TouchableOpacity);
|
|
70
|
+
await act(async () => {
|
|
71
|
+
await memberListButtons[1].props.onPress();
|
|
72
|
+
});
|
|
69
73
|
expect(mockedNavigate).toBeCalledWith(Routes.AddMemberStack, {
|
|
70
74
|
screen: Routes.SharingSelectPermission,
|
|
71
75
|
params: { unit: { id: 1 } },
|
|
72
76
|
});
|
|
73
77
|
});
|
|
78
|
+
|
|
79
|
+
it('add new member but reach limit', async () => {
|
|
80
|
+
let tree;
|
|
81
|
+
await act(async () => {
|
|
82
|
+
tree = await create(
|
|
83
|
+
wrapComponent(route, {
|
|
84
|
+
auth: {
|
|
85
|
+
account: {
|
|
86
|
+
user: {
|
|
87
|
+
permissions: {
|
|
88
|
+
max_members_per_unit: 0,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
const instance = tree.root;
|
|
97
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
98
|
+
const memberListButtons = instance.findAllByType(TouchableOpacity);
|
|
99
|
+
await act(async () => {
|
|
100
|
+
await memberListButtons[1].props.onPress();
|
|
101
|
+
});
|
|
102
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
103
|
+
expect(spyToastError).toBeCalledWith(
|
|
104
|
+
getTranslate('en', 'reach_max_members_per_unit')
|
|
105
|
+
);
|
|
106
|
+
});
|
|
74
107
|
});
|
|
@@ -163,7 +163,7 @@ const AddSubUnit = ({ route }) => {
|
|
|
163
163
|
|
|
164
164
|
const validateData = useMemo(() => {
|
|
165
165
|
if (isAddUnit) {
|
|
166
|
-
return roomName === '' || wallpaper === '' || location.description
|
|
166
|
+
return roomName === '' || wallpaper === '' || !location.description;
|
|
167
167
|
} else {
|
|
168
168
|
return roomName === '' || wallpaper === '';
|
|
169
169
|
}
|
|
@@ -62,6 +62,9 @@ describe('Test AddSubUnit', () => {
|
|
|
62
62
|
unit: {
|
|
63
63
|
id: 1,
|
|
64
64
|
name: 'Unit name',
|
|
65
|
+
location: {
|
|
66
|
+
description: 'location',
|
|
67
|
+
},
|
|
65
68
|
},
|
|
66
69
|
},
|
|
67
70
|
};
|
|
@@ -187,7 +190,9 @@ describe('Test AddSubUnit', () => {
|
|
|
187
190
|
it('test create Unit', async () => {
|
|
188
191
|
route.params = {
|
|
189
192
|
...route.params,
|
|
190
|
-
location:
|
|
193
|
+
location: {
|
|
194
|
+
description: 'Unit address',
|
|
195
|
+
},
|
|
191
196
|
isAddUnit: true,
|
|
192
197
|
};
|
|
193
198
|
mock.onPost(API.UNIT.CREATE_UNIT()).reply(200, {
|
|
@@ -231,7 +236,9 @@ describe('Test AddSubUnit', () => {
|
|
|
231
236
|
it('test create Unit Fail', async () => {
|
|
232
237
|
route.params = {
|
|
233
238
|
...route.params,
|
|
234
|
-
location:
|
|
239
|
+
location: {
|
|
240
|
+
description: 'Unit address',
|
|
241
|
+
},
|
|
235
242
|
isAddUnit: true,
|
|
236
243
|
};
|
|
237
244
|
mock.onPost(API.UNIT.CREATE_UNIT()).reply(400);
|
|
@@ -270,7 +277,13 @@ describe('Test AddSubUnit', () => {
|
|
|
270
277
|
isAddSubUnit: true,
|
|
271
278
|
routeName: 'DashboardStack',
|
|
272
279
|
stationId: undefined,
|
|
273
|
-
unitData: {
|
|
280
|
+
unitData: {
|
|
281
|
+
id: 1,
|
|
282
|
+
name: 'Unit name',
|
|
283
|
+
location: {
|
|
284
|
+
description: 'location',
|
|
285
|
+
},
|
|
286
|
+
},
|
|
274
287
|
unitId: 1,
|
|
275
288
|
},
|
|
276
289
|
});
|
|
@@ -7,61 +7,84 @@ import AddDeviceIcon from '../../../assets/images/Popover/Dashboard/AddDevice.sv
|
|
|
7
7
|
import SmartAccount from '../../../assets/images/Popover/Dashboard/SmartAccount.svg';
|
|
8
8
|
import AddMemberIcon from '../../../assets/images/Popover/Dashboard/AddMember.svg';
|
|
9
9
|
import { useNavigation } from '@react-navigation/native';
|
|
10
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
11
|
+
import { useBackendPermission } from '../../utils/Permission/backend';
|
|
10
12
|
|
|
11
13
|
const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
|
|
12
14
|
const t = useTranslations();
|
|
13
15
|
const navigation = useNavigation();
|
|
16
|
+
const permissions = useBackendPermission();
|
|
14
17
|
|
|
15
18
|
const onItemClick = useCallback(
|
|
16
|
-
(
|
|
19
|
+
(item) => {
|
|
17
20
|
setHideAdd(true);
|
|
18
21
|
afterItemClick();
|
|
19
|
-
|
|
22
|
+
item.onClick && item.onClick();
|
|
20
23
|
},
|
|
21
|
-
[setHideAdd, afterItemClick
|
|
24
|
+
[setHideAdd, afterItemClick]
|
|
22
25
|
);
|
|
23
26
|
|
|
24
27
|
const listItem = useMemo(() => {
|
|
25
28
|
return [
|
|
26
29
|
{
|
|
27
30
|
id: 'add_sub_unit',
|
|
28
|
-
route: Routes.AddSubUnitStack,
|
|
29
31
|
text: t('sub_unit'),
|
|
30
32
|
image: <AddSubUnitIcon width={43} height={43} />,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
onClick: () => {
|
|
34
|
+
// 2 is station favorite and smart
|
|
35
|
+
if (unit.stations.length - 2 >= permissions.max_stations_per_unit) {
|
|
36
|
+
ToastBottomHelper.error(t('reach_max_stations_per_unit'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
navigation.navigate(Routes.AddSubUnitStack, {
|
|
40
|
+
screen: Routes.AddSubUnit,
|
|
41
|
+
params: { unit, isInsideUnit: true },
|
|
42
|
+
});
|
|
34
43
|
},
|
|
35
44
|
},
|
|
36
45
|
{
|
|
37
46
|
id: 'add_member',
|
|
38
|
-
route: Routes.AddMemberStack,
|
|
39
47
|
text: t('member'),
|
|
40
48
|
image: <AddMemberIcon width={43} height={43} />,
|
|
41
|
-
|
|
49
|
+
onClick: () =>
|
|
50
|
+
navigation.navigate(Routes.AddMemberStack, {
|
|
51
|
+
screen: Routes.SharingSelectPermission,
|
|
52
|
+
params: { unit },
|
|
53
|
+
}),
|
|
42
54
|
},
|
|
43
55
|
{
|
|
44
56
|
id: 'add_device',
|
|
45
|
-
route: Routes.AddGatewayStack,
|
|
46
57
|
text: t('device'),
|
|
47
58
|
image: <AddDeviceIcon width={43} height={43} />,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
onClick: () => {
|
|
60
|
+
let hasPermission = false;
|
|
61
|
+
Object.keys(permissions).forEach((key) => {
|
|
62
|
+
if (key.includes('plug_and_play') && permissions[key]) {
|
|
63
|
+
hasPermission = true;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
if (!hasPermission) {
|
|
67
|
+
ToastBottomHelper.error(t('not_support_plug_and_play'));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
navigation.navigate(Routes.AddGatewayStack, {
|
|
71
|
+
screen: Routes.SelectDeviceType,
|
|
72
|
+
params: { unit },
|
|
73
|
+
});
|
|
51
74
|
},
|
|
52
75
|
},
|
|
53
76
|
{
|
|
54
77
|
id: 'add_smart_account',
|
|
55
|
-
route: Routes.SmartAccountStack,
|
|
56
78
|
text: t('name_smart_account'),
|
|
57
79
|
image: <SmartAccount width={43} height={43} />,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
80
|
+
onClick: () =>
|
|
81
|
+
navigation.navigate(Routes.SmartAccountStack, {
|
|
82
|
+
screen: Routes.SmartAccount,
|
|
83
|
+
params: { unitId: unit?.id, unitName: unit?.name },
|
|
84
|
+
}),
|
|
62
85
|
},
|
|
63
86
|
];
|
|
64
|
-
}, [t, unit]);
|
|
87
|
+
}, [t, unit, navigation, permissions]);
|
|
65
88
|
|
|
66
89
|
const hideAddModal = useCallback(() => {
|
|
67
90
|
setHideAdd(false);
|
|
@@ -5,13 +5,15 @@ import MenuActionAddnew from '../../../commons/MenuActionAddnew';
|
|
|
5
5
|
import { SCProvider } from '../../../context';
|
|
6
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
7
|
import AddMenu from '../AddMenu';
|
|
8
|
+
import { useNavigation } from '@react-navigation/native';
|
|
9
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
10
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
8
11
|
|
|
9
|
-
const mockedNavigate = jest.fn();
|
|
10
12
|
const mockedAfterItemClick = jest.fn();
|
|
11
13
|
const mockedHideAddModal = jest.fn();
|
|
12
14
|
|
|
13
|
-
const wrapComponent = (unit) => (
|
|
14
|
-
<SCProvider initState={mockSCStore(
|
|
15
|
+
const wrapComponent = (unit, storeData = {}) => (
|
|
16
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
15
17
|
<AddMenu
|
|
16
18
|
unit={unit}
|
|
17
19
|
afterItemClick={mockedAfterItemClick}
|
|
@@ -21,17 +23,15 @@ const wrapComponent = (unit) => (
|
|
|
21
23
|
</SCProvider>
|
|
22
24
|
);
|
|
23
25
|
|
|
24
|
-
jest.mock('@react-navigation/native', () => {
|
|
25
|
-
return {
|
|
26
|
-
...jest.requireActual('@react-navigation/native'),
|
|
27
|
-
useNavigation: () => ({
|
|
28
|
-
navigate: mockedNavigate,
|
|
29
|
-
}),
|
|
30
|
-
useIsFocused: jest.fn(),
|
|
31
|
-
};
|
|
32
|
-
});
|
|
33
|
-
|
|
34
26
|
describe('Test AddMenu Unit', () => {
|
|
27
|
+
const mockedNavigate = useNavigation().navigate;
|
|
28
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
mockedNavigate.mockClear();
|
|
32
|
+
spyToastError.mockClear();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
35
|
let tree;
|
|
36
36
|
it('render AddMenu without route', async () => {
|
|
37
37
|
let unit = { id: 1, name: 'Unit 1' };
|
|
@@ -68,8 +68,9 @@ describe('Test AddMenu Unit', () => {
|
|
|
68
68
|
const menuActionAddnew = instance.findByType(MenuActionAddnew);
|
|
69
69
|
await act(async () => {
|
|
70
70
|
menuActionAddnew.props.onItemClick({
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
onClick: () => {
|
|
72
|
+
mockedNavigate('route test', 'data test');
|
|
73
|
+
},
|
|
73
74
|
});
|
|
74
75
|
});
|
|
75
76
|
|
|
@@ -77,4 +78,56 @@ describe('Test AddMenu Unit', () => {
|
|
|
77
78
|
expect(mockedAfterItemClick).toHaveBeenCalled();
|
|
78
79
|
expect(mockedNavigate).toHaveBeenCalledWith('route test', 'data test');
|
|
79
80
|
});
|
|
81
|
+
|
|
82
|
+
it('add new device but have no permission', async () => {
|
|
83
|
+
let unit = { id: 1, name: 'Unit 1' };
|
|
84
|
+
await act(async () => {
|
|
85
|
+
tree = await create(
|
|
86
|
+
wrapComponent(unit, {
|
|
87
|
+
auth: {
|
|
88
|
+
account: {
|
|
89
|
+
user: {
|
|
90
|
+
permissions: {},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const instance = tree.root;
|
|
99
|
+
const menuActionAddnew = instance.findByType(MenuActionAddnew);
|
|
100
|
+
await act(async () => {
|
|
101
|
+
menuActionAddnew.props.onItemClick(menuActionAddnew.props.dataActions[2]);
|
|
102
|
+
});
|
|
103
|
+
expect(spyToastError).toBeCalledWith(
|
|
104
|
+
getTranslate('en', 'not_support_plug_and_play')
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('add new device has permission', async () => {
|
|
109
|
+
let unit = { id: 1, name: 'Unit 1' };
|
|
110
|
+
await act(async () => {
|
|
111
|
+
tree = await create(
|
|
112
|
+
wrapComponent(unit, {
|
|
113
|
+
auth: {
|
|
114
|
+
account: {
|
|
115
|
+
user: {
|
|
116
|
+
permissions: {
|
|
117
|
+
plug_and_play_zigbee: true,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const instance = tree.root;
|
|
127
|
+
const menuActionAddnew = instance.findByType(MenuActionAddnew);
|
|
128
|
+
await act(async () => {
|
|
129
|
+
menuActionAddnew.props.onItemClick(menuActionAddnew.props.dataActions[2]);
|
|
130
|
+
});
|
|
131
|
+
expect(spyToastError).not.toBeCalled();
|
|
132
|
+
});
|
|
80
133
|
});
|
|
@@ -59,7 +59,7 @@ const AutomateScript = ({ automate, onPress, isSelected }) => {
|
|
|
59
59
|
</Text>
|
|
60
60
|
<View style={styles.descriptionContainer}>
|
|
61
61
|
<Text numberOfLines={1} type={'Label'} color={Colors.Gray7}>
|
|
62
|
-
{
|
|
62
|
+
{t('created_by', { name: author })}
|
|
63
63
|
</Text>
|
|
64
64
|
<IconOutline name="right" size={12} />
|
|
65
65
|
</View>
|