@eohjsc/react-native-smart-city 0.4.77 → 0.4.79
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/ActionTemplate/SwitchButtonAction.js +55 -0
- package/src/commons/ActionTemplate/__test__/SwitchButtonAction.test.js +55 -0
- package/src/commons/ActionTemplate/__test__/index.test.js +24 -0
- package/src/commons/ActionTemplate/index.js +3 -0
- package/src/commons/Auth/AccountItem.js +5 -4
- package/src/commons/ChartAggregationOption/index.js +1 -2
- package/src/commons/Sharing/MemberList.js +1 -0
- package/src/commons/Sharing/RowMember.js +13 -14
- package/src/commons/SubUnit/DeviceTemplate/ConfigAndEvaluation/ConfigAndEvaluation.js +8 -2
- package/src/commons/SubUnit/DeviceTemplate/ConfigValue/ConfigValue.js +10 -2
- package/src/commons/SubUnit/DeviceTemplate/DeviceTemplate.js +2 -6
- package/src/commons/SubUnit/DeviceTemplate/EvaluationOverConfig/EvaluationOverConfig.js +8 -2
- package/src/commons/SubUnit/DeviceTemplate/styles/ConfigValueStyles.js +10 -0
- package/src/commons/SubUnit/ShortDetail.js +4 -5
- package/src/navigations/AddMemberStack.js +2 -2
- package/src/screens/Automate/AddNewAction/ChooseAction.js +12 -3
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +0 -2
- package/src/screens/Automate/AddNewAction/Styles/SetupSensorStyles.js +1 -0
- package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +188 -0
- package/src/screens/Device/components/VisualChart.js +10 -3
- package/src/screens/HanetCamera/styles/memberInfoStyles.js +1 -1
- package/src/screens/Notification/styles/indexStyles.js +2 -1
- package/src/screens/Sharing/SelectUser.js +9 -6
- package/src/screens/Sharing/{SelectPermission.js → SharingSelectPermission.js} +4 -2
- package/src/screens/Sharing/Styles/SelectPermissionStyles.js +4 -0
- package/src/screens/Sharing/Styles/inforMemberUnitStyles.js +1 -1
- package/src/screens/Sharing/__test__/SelectUser.test.js +46 -4
- package/src/screens/Sharing/__test__/{SelectPermission.test.js → SharingSelectPermission.test.js} +4 -5
- package/src/utils/I18n/translations/en.js +2 -0
- package/src/utils/I18n/translations/vi.js +3 -0
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { TouchableOpacity } from 'react-native';
|
|
3
|
+
import AccessibilityLabel from '../../configs/AccessibilityLabel';
|
|
4
|
+
import Text from '../Text';
|
|
5
|
+
import styles from './OnOffButtonActionStyles';
|
|
6
|
+
|
|
7
|
+
const SwitchButtonAction = ({ title, configuration, onPress, template }) => {
|
|
8
|
+
const { text_on, text_off, action_on, action_off } = configuration;
|
|
9
|
+
const onPressActionOn = useCallback(() => {
|
|
10
|
+
onPress &&
|
|
11
|
+
onPress({
|
|
12
|
+
...configuration,
|
|
13
|
+
name: text_on,
|
|
14
|
+
action: action_on,
|
|
15
|
+
action_off: null,
|
|
16
|
+
template,
|
|
17
|
+
});
|
|
18
|
+
}, [onPress, configuration, text_on, action_on, template]);
|
|
19
|
+
|
|
20
|
+
const onPressActionOff = useCallback(() => {
|
|
21
|
+
onPress &&
|
|
22
|
+
onPress({
|
|
23
|
+
...configuration,
|
|
24
|
+
name: text_off,
|
|
25
|
+
action: action_off,
|
|
26
|
+
action_on: null,
|
|
27
|
+
template,
|
|
28
|
+
});
|
|
29
|
+
}, [onPress, configuration, text_off, action_off, template]);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
<TouchableOpacity onPress={onPressActionOn}>
|
|
34
|
+
<Text
|
|
35
|
+
type="H4"
|
|
36
|
+
style={styles.textWithLine}
|
|
37
|
+
accessibilityLabel={AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE}
|
|
38
|
+
>
|
|
39
|
+
{title} {text_on}
|
|
40
|
+
</Text>
|
|
41
|
+
</TouchableOpacity>
|
|
42
|
+
<TouchableOpacity onPress={onPressActionOff}>
|
|
43
|
+
<Text
|
|
44
|
+
type="H4"
|
|
45
|
+
style={styles.textWithLine}
|
|
46
|
+
accessibilityLabel={AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE}
|
|
47
|
+
>
|
|
48
|
+
{title} {text_off}
|
|
49
|
+
</Text>
|
|
50
|
+
</TouchableOpacity>
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default SwitchButtonAction;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
import { TouchableOpacity } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { SCProvider } from '../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import Text from '../../Text';
|
|
8
|
+
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
9
|
+
import SwitchButtonAction from '../SwitchButtonAction';
|
|
10
|
+
|
|
11
|
+
const wrapComponent = (configuration, onPress) => (
|
|
12
|
+
<SCProvider initState={mockSCStore({})}>
|
|
13
|
+
<SwitchButtonAction
|
|
14
|
+
configuration={configuration}
|
|
15
|
+
onPress={onPress}
|
|
16
|
+
title={'Cong tac 1'}
|
|
17
|
+
template={'switch_button_action_template'}
|
|
18
|
+
/>
|
|
19
|
+
</SCProvider>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
describe('Test SwitchButtonAction', () => {
|
|
23
|
+
let tree;
|
|
24
|
+
|
|
25
|
+
it('test onPress', async () => {
|
|
26
|
+
const configuration = {
|
|
27
|
+
text_on: 'On',
|
|
28
|
+
text_off: 'Off',
|
|
29
|
+
action_off: 'f49e1577-493d-4bae-a9ab-3b0f96a4ec52',
|
|
30
|
+
action_on: '94600cbe-2035-47d5-bd43-89ace5d59796',
|
|
31
|
+
};
|
|
32
|
+
const mockFuntion = jest.fn();
|
|
33
|
+
await act(async () => {
|
|
34
|
+
tree = await renderer.create(wrapComponent(configuration, mockFuntion));
|
|
35
|
+
});
|
|
36
|
+
const instance = tree.root;
|
|
37
|
+
const touchOpacity = instance.findAllByType(TouchableOpacity);
|
|
38
|
+
|
|
39
|
+
expect(touchOpacity).toHaveLength(2);
|
|
40
|
+
await act(async () => {
|
|
41
|
+
touchOpacity[0].props.onPress();
|
|
42
|
+
touchOpacity[1].props.onPress();
|
|
43
|
+
});
|
|
44
|
+
expect(mockFuntion).toHaveBeenCalled();
|
|
45
|
+
|
|
46
|
+
const textTitle = instance.findAll(
|
|
47
|
+
(el) =>
|
|
48
|
+
el.props.accessibilityLabel ===
|
|
49
|
+
AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE && el.type === Text
|
|
50
|
+
);
|
|
51
|
+
expect(textTitle).toHaveLength(2);
|
|
52
|
+
expect(textTitle[0].props.children).toEqual(['Cong tac 1', ' ', 'On']);
|
|
53
|
+
expect(textTitle[1].props.children).toEqual(['Cong tac 1', ' ', 'Off']);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -7,6 +7,8 @@ import { mockSCStore } from '../../../context/mockStore';
|
|
|
7
7
|
import SelectActionCard from '../../SelectActionCard';
|
|
8
8
|
import Modal from 'react-native-modal';
|
|
9
9
|
import ThreeButtonAction from '../ThreeButtonAction';
|
|
10
|
+
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
11
|
+
import Text from '../../Text';
|
|
10
12
|
|
|
11
13
|
const mockOnSelectAction = jest.fn();
|
|
12
14
|
|
|
@@ -35,6 +37,16 @@ describe('Test ActionTemplate', () => {
|
|
|
35
37
|
is_display_lock: true,
|
|
36
38
|
},
|
|
37
39
|
};
|
|
40
|
+
let switchTemplate = {
|
|
41
|
+
title: '',
|
|
42
|
+
template: 'switch_button_action_template',
|
|
43
|
+
configuration: {
|
|
44
|
+
text_on: 'On',
|
|
45
|
+
text_off: 'Off',
|
|
46
|
+
action_off: 'f49e1577-493d-4bae-a9ab-3b0f96a4ec52',
|
|
47
|
+
action_on: '94600cbe-2035-47d5-bd43-89ace5d59796',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
38
50
|
|
|
39
51
|
it('test onPress SelectActionCard', async () => {
|
|
40
52
|
await act(async () => {
|
|
@@ -75,4 +87,16 @@ describe('Test ActionTemplate', () => {
|
|
|
75
87
|
template: 'three_button_action_template',
|
|
76
88
|
});
|
|
77
89
|
});
|
|
90
|
+
it('test render SwitchButtonAction', async () => {
|
|
91
|
+
await act(async () => {
|
|
92
|
+
tree = await renderer.create(wrapComponent(switchTemplate));
|
|
93
|
+
});
|
|
94
|
+
const instance = tree.root;
|
|
95
|
+
const textTitle = instance.findAll(
|
|
96
|
+
(el) =>
|
|
97
|
+
el.props.accessibilityLabel ===
|
|
98
|
+
AccessibilityLabel.ON_OFF_BUTTON_ACTION_TITLE && el.type === Text
|
|
99
|
+
);
|
|
100
|
+
expect(textTitle).toHaveLength(2);
|
|
101
|
+
});
|
|
78
102
|
});
|
|
@@ -12,6 +12,7 @@ import { ModalCustom } from '../Modal';
|
|
|
12
12
|
import CurtainAction from './CurtainAction';
|
|
13
13
|
import OnOffSmartLockAction from './OnOffSmartLockAction';
|
|
14
14
|
import { DEVICE_TYPE } from '../../configs/Constants';
|
|
15
|
+
import SwitchButtonAction from './SwitchButtonAction';
|
|
15
16
|
|
|
16
17
|
const ActionTemplate = memo(({ device, item, onSelectAction }) => {
|
|
17
18
|
const t = useTranslations();
|
|
@@ -61,6 +62,8 @@ const ActionTemplate = memo(({ device, item, onSelectAction }) => {
|
|
|
61
62
|
return <CurtainAction {...item} onPress={onPressSelectAction} />;
|
|
62
63
|
case 'OnOffSmartLockActionTemplate':
|
|
63
64
|
return <OnOffSmartLockAction {...item} onPress={onPressSelectAction} />;
|
|
65
|
+
case 'switch_button_action_template':
|
|
66
|
+
return <SwitchButtonAction {...item} onPress={onPressSelectAction} />;
|
|
64
67
|
default:
|
|
65
68
|
return null;
|
|
66
69
|
}
|
|
@@ -7,6 +7,7 @@ import Avatar from '../../../assets/images/avatar.svg';
|
|
|
7
7
|
import AccessibilityLabel from '../../configs/AccessibilityLabel';
|
|
8
8
|
|
|
9
9
|
const AccountItem = ({ account }) => {
|
|
10
|
+
const { name, email, phone_number } = account;
|
|
10
11
|
return (
|
|
11
12
|
<View style={styles.container}>
|
|
12
13
|
<View styles={styles.wrap}>
|
|
@@ -14,18 +15,18 @@ const AccountItem = ({ account }) => {
|
|
|
14
15
|
</View>
|
|
15
16
|
<View style={styles.space} />
|
|
16
17
|
<View style={styles.wrap}>
|
|
17
|
-
{(
|
|
18
|
+
{(name || email) && (
|
|
18
19
|
<Text style={{ color: Colors.Gray9 }}>
|
|
19
|
-
{
|
|
20
|
+
{name || shortEmailName(email)}
|
|
20
21
|
</Text>
|
|
21
22
|
)}
|
|
22
23
|
|
|
23
|
-
{
|
|
24
|
+
{!!phone_number /* Can't write test for this case, use !! to avoid app crash when phone_number is '' */ && (
|
|
24
25
|
<Text
|
|
25
26
|
style={{ color: Colors.Gray8 }}
|
|
26
27
|
accessibilityLabel={AccessibilityLabel.TEXT_PHONE_NUMBER_ITEM}
|
|
27
28
|
>
|
|
28
|
-
{
|
|
29
|
+
{phone_number}
|
|
29
30
|
</Text>
|
|
30
31
|
)}
|
|
31
32
|
</View>
|
|
@@ -9,7 +9,6 @@ const defaultOptions = [
|
|
|
9
9
|
title: 'D',
|
|
10
10
|
data: 'date',
|
|
11
11
|
},
|
|
12
|
-
|
|
13
12
|
{
|
|
14
13
|
title: 'W',
|
|
15
14
|
data: 'week',
|
|
@@ -33,7 +32,7 @@ const ItemButton = ({ title, onPress, isSelected }) => {
|
|
|
33
32
|
style={[styles.button, isSelected && styles.selectedButton]}
|
|
34
33
|
>
|
|
35
34
|
<View>
|
|
36
|
-
<Text bold color={isSelected
|
|
35
|
+
<Text bold color={isSelected ? Colors.Primary : Colors.Gray9}>
|
|
37
36
|
{title}
|
|
38
37
|
</Text>
|
|
39
38
|
</View>
|
|
@@ -31,21 +31,22 @@ const RowMember = memo(
|
|
|
31
31
|
}) => {
|
|
32
32
|
const t = useTranslations();
|
|
33
33
|
const { navigate } = useNavigation();
|
|
34
|
+
const { id, name, phone_number, email, share_id, avatar } = member;
|
|
34
35
|
const [role, roleColor] = useMemo(
|
|
35
36
|
() =>
|
|
36
|
-
|
|
37
|
+
id === ownerId
|
|
37
38
|
? [t('owner'), Colors.Primary]
|
|
38
|
-
:
|
|
39
|
+
: id === currentUserId
|
|
39
40
|
? [t('me'), Colors.Primary]
|
|
40
41
|
: [t('member'), Colors.Gray6],
|
|
41
|
-
[currentUserId,
|
|
42
|
+
[currentUserId, id, ownerId, t]
|
|
42
43
|
);
|
|
43
44
|
const firstWordsInName = useMemo(() => {
|
|
44
|
-
const wordTemp =
|
|
45
|
+
const wordTemp = name || shortEmailName(email) || '';
|
|
45
46
|
return wordTemp?.charAt();
|
|
46
|
-
}, [
|
|
47
|
+
}, [email, name]);
|
|
47
48
|
|
|
48
|
-
if (
|
|
49
|
+
if (id === ownerId && share_id) {
|
|
49
50
|
return null;
|
|
50
51
|
}
|
|
51
52
|
const circleColorTypes = {
|
|
@@ -74,11 +75,8 @@ const RowMember = memo(
|
|
|
74
75
|
<View style={styles.Border}>
|
|
75
76
|
{!!leftIcon && (
|
|
76
77
|
<View style={styles.paddingLeft16}>
|
|
77
|
-
{
|
|
78
|
-
<Image
|
|
79
|
-
source={{ uri: member?.avatar }}
|
|
80
|
-
style={styles.avatar}
|
|
81
|
-
/>
|
|
78
|
+
{avatar ? (
|
|
79
|
+
<Image source={{ uri: avatar }} style={styles.avatar} />
|
|
82
80
|
) : (
|
|
83
81
|
<CircleView size={40} backgroundColor={circleColor} center>
|
|
84
82
|
<Text color={Colors.White}>{firstWordsInName}</Text>
|
|
@@ -88,16 +86,17 @@ const RowMember = memo(
|
|
|
88
86
|
)}
|
|
89
87
|
<View style={styles.columnFlex}>
|
|
90
88
|
<Text style={styles.titleName}>
|
|
91
|
-
{
|
|
89
|
+
{name || shortEmailName(email) || ''}
|
|
92
90
|
</Text>
|
|
93
|
-
{
|
|
91
|
+
{/* Can't write test for this case, use !! to avoid app crash when phone_number is '' */}
|
|
92
|
+
{!!phone_number && (
|
|
94
93
|
<Text
|
|
95
94
|
style={styles.status}
|
|
96
95
|
accessibilityLabel={
|
|
97
96
|
AccessibilityLabel.TEXT_PHONE_NUMBER_UNIT_MEMBER
|
|
98
97
|
}
|
|
99
98
|
>
|
|
100
|
-
{
|
|
99
|
+
{phone_number}
|
|
101
100
|
</Text>
|
|
102
101
|
)}
|
|
103
102
|
</View>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import styles from '../styles/ConfigValueStyles';
|
|
3
|
-
import { View } from 'react-native';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import LastUpdatedText from '../../../Device/LastUpdatedText';
|
|
6
6
|
import { EvaluationConfigWrapper } from '../EvaluationOverConfig/EvaluationOverConfig';
|
|
@@ -17,7 +17,13 @@ const ConfigAndEvaluationDisplay = memo(
|
|
|
17
17
|
<IconComponent icon={icon_kit || icon} />
|
|
18
18
|
</View>
|
|
19
19
|
<View style={styles.rowTop}>
|
|
20
|
-
<Text
|
|
20
|
+
<Text
|
|
21
|
+
numberOfLines={1}
|
|
22
|
+
semibold
|
|
23
|
+
style={
|
|
24
|
+
Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle
|
|
25
|
+
}
|
|
26
|
+
>
|
|
21
27
|
{stationItem?.configuration?.config_data?.name}
|
|
22
28
|
</Text>
|
|
23
29
|
</View>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import styles from '../styles/ConfigValueStyles';
|
|
3
|
-
import { View } from 'react-native';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import { useConfigGlobalState } from '../../../../iot/states';
|
|
6
6
|
import { useWatchConfigs } from '../../../../hooks/IoT';
|
|
@@ -25,7 +25,15 @@ const ConfigValue = ({ device, stationItem }) => {
|
|
|
25
25
|
<IconComponent icon={icon_kit || icon} />
|
|
26
26
|
</View>
|
|
27
27
|
<View style={styles.rowTop}>
|
|
28
|
-
<Text
|
|
28
|
+
<Text
|
|
29
|
+
numberOfLines={1}
|
|
30
|
+
semibold
|
|
31
|
+
style={
|
|
32
|
+
Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle
|
|
33
|
+
}
|
|
34
|
+
>
|
|
35
|
+
{stationItem?.configuration?.config_data?.name}
|
|
36
|
+
</Text>
|
|
29
37
|
</View>
|
|
30
38
|
<View style={styles.rowBottom}>
|
|
31
39
|
<Text style={styles.textValue} bold>
|
|
@@ -3,18 +3,14 @@ import { getTemplate } from './';
|
|
|
3
3
|
import ItemDeviceWrapper from '../../Device/ItemDeviceWrapper';
|
|
4
4
|
|
|
5
5
|
export const DeviceTemplate = memo(
|
|
6
|
-
({ device, stationItem, unit, station,
|
|
6
|
+
({ device, stationItem, unit, station, key }) => {
|
|
7
7
|
const Template = getTemplate(stationItem);
|
|
8
8
|
if (!Template) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
11
|
return (
|
|
12
12
|
<ItemDeviceWrapper device={device} unit={unit} station={station}>
|
|
13
|
-
<Template.Display
|
|
14
|
-
device={device}
|
|
15
|
-
stationItem={stationItem}
|
|
16
|
-
index={index}
|
|
17
|
-
/>
|
|
13
|
+
<Template.Display device={device} stationItem={stationItem} key={key} />
|
|
18
14
|
</ItemDeviceWrapper>
|
|
19
15
|
);
|
|
20
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import styles from '../styles/ConfigValueStyles';
|
|
3
|
-
import { View } from 'react-native';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import { useConfigGlobalState } from '../../../../iot/states';
|
|
6
6
|
import {
|
|
@@ -54,7 +54,13 @@ const EvaluationOverConfigDisplay = memo(
|
|
|
54
54
|
<IconComponent icon={icon_kit || icon} />
|
|
55
55
|
</View>
|
|
56
56
|
<View style={styles.rowTop}>
|
|
57
|
-
<Text
|
|
57
|
+
<Text
|
|
58
|
+
numberOfLines={1}
|
|
59
|
+
semibold
|
|
60
|
+
style={
|
|
61
|
+
Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle
|
|
62
|
+
}
|
|
63
|
+
>
|
|
58
64
|
{stationItem?.configuration?.config_data?.name}
|
|
59
65
|
</Text>
|
|
60
66
|
</View>
|
|
@@ -32,4 +32,14 @@ export default StyleSheet.create({
|
|
|
32
32
|
marginTop10: {
|
|
33
33
|
marginTop: 10,
|
|
34
34
|
},
|
|
35
|
+
iosStyle: {
|
|
36
|
+
fontSize: 14,
|
|
37
|
+
lineHeight: 22,
|
|
38
|
+
},
|
|
39
|
+
androidStyle: {
|
|
40
|
+
fontSize: 14,
|
|
41
|
+
lineHeight: 22,
|
|
42
|
+
includeFontPadding: false,
|
|
43
|
+
marginBottom: 8,
|
|
44
|
+
},
|
|
35
45
|
});
|
|
@@ -106,13 +106,12 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
106
106
|
});
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
const renderSubUnitItem = (device, stationItem
|
|
109
|
+
const renderSubUnitItem = (device, stationItem) => {
|
|
110
110
|
return (
|
|
111
111
|
<DeviceTemplate
|
|
112
112
|
device={device}
|
|
113
113
|
stationItem={stationItem}
|
|
114
|
-
|
|
115
|
-
key={index}
|
|
114
|
+
key={`device-template-${stationItem.id}`}
|
|
116
115
|
unit={unit}
|
|
117
116
|
station={station}
|
|
118
117
|
/>
|
|
@@ -126,7 +125,7 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
126
125
|
|
|
127
126
|
return station.devices
|
|
128
127
|
.map((device, index) => {
|
|
129
|
-
|
|
128
|
+
let displays = [];
|
|
130
129
|
if (device.device_type === DEVICE_TYPE.HANET) {
|
|
131
130
|
displays.push(
|
|
132
131
|
<ItemHanetDevice
|
|
@@ -157,7 +156,7 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
157
156
|
/>
|
|
158
157
|
);
|
|
159
158
|
}
|
|
160
|
-
if (device.station_items) {
|
|
159
|
+
if (device.station_items?.length) {
|
|
161
160
|
displays.push(
|
|
162
161
|
...device.station_items.map(renderSubUnitItem.bind(device, device))
|
|
163
162
|
);
|
|
@@ -2,10 +2,10 @@ import { createStackNavigator } from '@react-navigation/stack';
|
|
|
2
2
|
import React, { memo } from 'react';
|
|
3
3
|
|
|
4
4
|
import AddCommonSelectUnit from '../screens/AddCommon/SelectUnit';
|
|
5
|
-
import SharingSelectPermission from '../screens/Sharing/SelectPermission';
|
|
6
|
-
import SharingInviteMembers from '../screens/Sharing/SelectUser';
|
|
7
5
|
import Route from '../utils/Route';
|
|
8
6
|
import { screenOptions } from './utils';
|
|
7
|
+
import SharingInviteMembers from '../screens/Sharing/SelectUser';
|
|
8
|
+
import SharingSelectPermission from '../screens/Sharing/SharingSelectPermission';
|
|
9
9
|
|
|
10
10
|
const Stack = createStackNavigator();
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ import NewActionWrapper from './NewActionWrapper';
|
|
|
14
14
|
import moment from 'moment';
|
|
15
15
|
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
16
16
|
|
|
17
|
-
const RenderActionItem = ({ device, item, handleOnSelectAction, index }) => {
|
|
17
|
+
const RenderActionItem = ({ device, item, handleOnSelectAction, index, t }) => {
|
|
18
18
|
item.index = index;
|
|
19
19
|
switch (item.template) {
|
|
20
20
|
case 'on_off_button_action_template':
|
|
@@ -23,6 +23,7 @@ const RenderActionItem = ({ device, item, handleOnSelectAction, index }) => {
|
|
|
23
23
|
case 'OnOffSimpleActionTemplate':
|
|
24
24
|
case 'curtain_action_template':
|
|
25
25
|
case 'OnOffSmartLockActionTemplate':
|
|
26
|
+
case 'switch_button_action_template':
|
|
26
27
|
return (
|
|
27
28
|
<ActionTemplate
|
|
28
29
|
device={device}
|
|
@@ -57,14 +58,20 @@ const RenderActionItem = ({ device, item, handleOnSelectAction, index }) => {
|
|
|
57
58
|
onSelectAction={handleOnSelectAction}
|
|
58
59
|
/>
|
|
59
60
|
);
|
|
61
|
+
default:
|
|
62
|
+
ToastBottomHelper.error(
|
|
63
|
+
t('template_not_supported', { template: item.template }),
|
|
64
|
+
'',
|
|
65
|
+
3000
|
|
66
|
+
);
|
|
67
|
+
return null;
|
|
60
68
|
}
|
|
61
69
|
};
|
|
62
70
|
|
|
63
71
|
const ChooseAction = ({ route }) => {
|
|
64
72
|
const t = useTranslations();
|
|
65
73
|
const { navigate } = useNavigation();
|
|
66
|
-
const { unitId, device, automateId, numberActionCanAdd } =
|
|
67
|
-
route?.params || {};
|
|
74
|
+
const { unitId, device, automateId, numberActionCanAdd } = route?.params;
|
|
68
75
|
const [data, setData] = useState([]);
|
|
69
76
|
const [actions, setActions] = useState([]);
|
|
70
77
|
|
|
@@ -141,10 +148,12 @@ const ChooseAction = ({ route }) => {
|
|
|
141
148
|
{!!data?.length &&
|
|
142
149
|
data.map((item, index) => (
|
|
143
150
|
<RenderActionItem
|
|
151
|
+
key={`action_item_${index}`}
|
|
144
152
|
device={device}
|
|
145
153
|
item={item}
|
|
146
154
|
index={index}
|
|
147
155
|
handleOnSelectAction={handleOnSelectAction}
|
|
156
|
+
t={t}
|
|
148
157
|
/>
|
|
149
158
|
))}
|
|
150
159
|
</View>
|
|
@@ -43,11 +43,9 @@ const valueEvaluationToOptions = (valueEvaluation) => {
|
|
|
43
43
|
|
|
44
44
|
const SetupConfigCondition = () => {
|
|
45
45
|
const t = useTranslations();
|
|
46
|
-
//
|
|
47
46
|
const { navigate } = useNavigation();
|
|
48
47
|
const { params = {} } = useRoute();
|
|
49
48
|
const { config, automate, closeScreen } = params;
|
|
50
|
-
//
|
|
51
49
|
const [selectedCondition, setSelectedCondition] = useState(undefined);
|
|
52
50
|
const [customCondition, setCustomCondition] = useState(undefined);
|
|
53
51
|
const [isShowModal, setIsShowModal] = useState(false);
|
|
@@ -13,6 +13,7 @@ import { TouchableOpacity } from 'react-native';
|
|
|
13
13
|
import SelectActionCard from '../../../../commons/SelectActionCard';
|
|
14
14
|
import { useNavigation } from '@react-navigation/native';
|
|
15
15
|
import { ToastBottomHelper } from '../../../../utils/Utils';
|
|
16
|
+
import { getTranslate } from '../../../../utils/I18n';
|
|
16
17
|
|
|
17
18
|
const mock = new MockAdapter(api.axiosInstance);
|
|
18
19
|
|
|
@@ -370,6 +371,35 @@ describe('Test ChooseAction', () => {
|
|
|
370
371
|
);
|
|
371
372
|
});
|
|
372
373
|
|
|
374
|
+
test('test press template wrong', async () => {
|
|
375
|
+
const config1 = 1;
|
|
376
|
+
const response = [
|
|
377
|
+
{
|
|
378
|
+
id: 1,
|
|
379
|
+
title: '',
|
|
380
|
+
template: 'TeamplateWorng',
|
|
381
|
+
configuration: {
|
|
382
|
+
allow_config_store_value: true,
|
|
383
|
+
config: config1,
|
|
384
|
+
action_on: '94ae262d-46e3-42ff-9d10-516831ecc830',
|
|
385
|
+
action_off: '94ae262d-46e3-42ff-9d10-516831ecc830',
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
];
|
|
389
|
+
mock.onGet(API.DEVICE.DISPLAY_ACTIONS(1)).reply(200, response);
|
|
390
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
391
|
+
await act(async () => {
|
|
392
|
+
tree = await renderer.create(wrapComponent(route));
|
|
393
|
+
});
|
|
394
|
+
expect(spyToastError).toBeCalledWith(
|
|
395
|
+
getTranslate('en', 'template_not_supported', {
|
|
396
|
+
template: response[0].template,
|
|
397
|
+
}),
|
|
398
|
+
'',
|
|
399
|
+
3000
|
|
400
|
+
);
|
|
401
|
+
});
|
|
402
|
+
|
|
373
403
|
test('test reach max can add', async () => {
|
|
374
404
|
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
375
405
|
|
|
@@ -435,4 +465,162 @@ describe('Test ChooseAction', () => {
|
|
|
435
465
|
3000
|
|
436
466
|
);
|
|
437
467
|
});
|
|
468
|
+
test('reach max can add actions', async () => {
|
|
469
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
470
|
+
|
|
471
|
+
const config1 = 1,
|
|
472
|
+
config2 = 2,
|
|
473
|
+
config3 = 3,
|
|
474
|
+
config4 = 4;
|
|
475
|
+
const response = [
|
|
476
|
+
{
|
|
477
|
+
id: 1,
|
|
478
|
+
title: '',
|
|
479
|
+
template: 'OnOffSimpleActionTemplate',
|
|
480
|
+
configuration: {
|
|
481
|
+
allow_config_store_value: true,
|
|
482
|
+
config: config1,
|
|
483
|
+
action_on: '94ae262d-46e3-42ff-9d10-516831ecc830',
|
|
484
|
+
action_off: '94ae262d-46e3-42ff-9d10-516831ecc830',
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
id: 2,
|
|
489
|
+
title: 'Fan Speed',
|
|
490
|
+
template: 'OptionsDropdownActionTemplate',
|
|
491
|
+
configuration: {
|
|
492
|
+
config: config2,
|
|
493
|
+
action: '05195362-75de-4db5-9e5e-98fef9d4910c',
|
|
494
|
+
allow_config_store_value: true,
|
|
495
|
+
options: [
|
|
496
|
+
{
|
|
497
|
+
text: 'Auto',
|
|
498
|
+
value_int: 1,
|
|
499
|
+
value_text: 'auto',
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
text: 'Level1',
|
|
503
|
+
value_int: 2,
|
|
504
|
+
value_text: 'level1',
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
icon: 'up',
|
|
508
|
+
icon_kit: 43,
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
id: 3,
|
|
513
|
+
title: '',
|
|
514
|
+
template: 'NumberUpDownActionTemplate',
|
|
515
|
+
configuration: {
|
|
516
|
+
keep_track_config: true,
|
|
517
|
+
config: config3,
|
|
518
|
+
allow_config_store_value: true,
|
|
519
|
+
action: 'b498234c-6c1a-452d-a1d1-87a314c20528',
|
|
520
|
+
min_value: 16,
|
|
521
|
+
max_value: 30,
|
|
522
|
+
text_format: '{number} \u00b0C',
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
id: 4,
|
|
527
|
+
title: '',
|
|
528
|
+
template: 'NumberUpDownActionTemplate',
|
|
529
|
+
configuration: {
|
|
530
|
+
config: config4,
|
|
531
|
+
allow_config_store_value: true,
|
|
532
|
+
action: '11111111-6c1a-452d-a1d1-87a314c20528',
|
|
533
|
+
min_value: 12,
|
|
534
|
+
max_value: 20,
|
|
535
|
+
text_format: '{number} \u00b0C',
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
];
|
|
539
|
+
mock.onGet(API.DEVICE.DISPLAY_ACTIONS(1)).reply(200, response);
|
|
540
|
+
route.params.numberActionCanAdd = 2;
|
|
541
|
+
await act(async () => {
|
|
542
|
+
tree = await renderer.create(wrapComponent(route));
|
|
543
|
+
});
|
|
544
|
+
const instance = tree.root;
|
|
545
|
+
|
|
546
|
+
const cards = instance.findAllByType(SelectActionCard);
|
|
547
|
+
|
|
548
|
+
await act(async () => {
|
|
549
|
+
cards.map((card) => card.props.onPress());
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
const simpleActionOn = instance.find(
|
|
553
|
+
(el) =>
|
|
554
|
+
el.props.accessibilityLabel ===
|
|
555
|
+
AccessibilityLabel.ON_OFF_SIMPLE_ACTION_ON &&
|
|
556
|
+
el.type === TouchableOpacity
|
|
557
|
+
);
|
|
558
|
+
await act(async () => {
|
|
559
|
+
await simpleActionOn.props.onPress();
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
const simpleActionOnOff = instance.find(
|
|
563
|
+
(el) =>
|
|
564
|
+
el.props.accessibilityLabel ===
|
|
565
|
+
AccessibilityLabel.ON_OFF_SIMPLE_ACTION_OFF &&
|
|
566
|
+
el.type === TouchableOpacity
|
|
567
|
+
);
|
|
568
|
+
await act(async () => {
|
|
569
|
+
await simpleActionOnOff.props.onPress();
|
|
570
|
+
});
|
|
571
|
+
const selectOptions = instance.findAll(
|
|
572
|
+
(item) =>
|
|
573
|
+
item.props.accessibilityLabel ===
|
|
574
|
+
AccessibilityLabel.OPTIONS_DROPDOWN_ACTION_CHOOSING_ITEM &&
|
|
575
|
+
item.type === TouchableOpacity
|
|
576
|
+
);
|
|
577
|
+
const touchOpacity = instance.find(
|
|
578
|
+
(item) =>
|
|
579
|
+
item.props.accessibilityLabel ===
|
|
580
|
+
AccessibilityLabel.OPTIONS_DROPDOWN_ACTION_DONE &&
|
|
581
|
+
item.type === TouchableOpacity
|
|
582
|
+
);
|
|
583
|
+
|
|
584
|
+
await act(async () => {
|
|
585
|
+
await selectOptions[0].props.onPress(0);
|
|
586
|
+
await touchOpacity.props.onPress();
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const buttonNumberUp = instance.findAll(
|
|
590
|
+
(item) =>
|
|
591
|
+
item.props.accessibilityLabel ===
|
|
592
|
+
AccessibilityLabel.NUMBER_UP_DOWN_ACTION_UP &&
|
|
593
|
+
item.type === TouchableOpacity
|
|
594
|
+
);
|
|
595
|
+
expect(buttonNumberUp).toHaveLength(2);
|
|
596
|
+
|
|
597
|
+
const buttonSaveNumberAction = instance.findAll(
|
|
598
|
+
(item) =>
|
|
599
|
+
item.props.accessibilityLabel ===
|
|
600
|
+
AccessibilityLabel.NUMBER_UP_DOWN_ACTION_DONE &&
|
|
601
|
+
item.type === TouchableOpacity
|
|
602
|
+
);
|
|
603
|
+
expect(buttonSaveNumberAction).toHaveLength(2);
|
|
604
|
+
|
|
605
|
+
await act(async () => {
|
|
606
|
+
await buttonNumberUp[0].props.onPress();
|
|
607
|
+
await buttonNumberUp[1].props.onPress();
|
|
608
|
+
await buttonSaveNumberAction[0].props.onPress();
|
|
609
|
+
await buttonSaveNumberAction[1].props.onPress();
|
|
610
|
+
});
|
|
611
|
+
const buttonSave = instance.find(
|
|
612
|
+
(el) =>
|
|
613
|
+
el.props.accessibilityLabel === AccessibilityLabel.BOTTOM_VIEW_MAIN &&
|
|
614
|
+
el.type === TouchableOpacity
|
|
615
|
+
);
|
|
616
|
+
await act(async () => {
|
|
617
|
+
await buttonSave.props.onPress();
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
expect(spyToastError).toBeCalledWith(
|
|
621
|
+
'You can only add more 2 actions',
|
|
622
|
+
null,
|
|
623
|
+
3000
|
|
624
|
+
);
|
|
625
|
+
});
|
|
438
626
|
});
|
|
@@ -123,6 +123,11 @@ const styles = StyleSheet.create({
|
|
|
123
123
|
width: 300,
|
|
124
124
|
height: 250,
|
|
125
125
|
},
|
|
126
|
+
titleView: {
|
|
127
|
+
flexDirection: 'row',
|
|
128
|
+
flex: 1,
|
|
129
|
+
lineHeight: 24,
|
|
130
|
+
},
|
|
126
131
|
});
|
|
127
132
|
|
|
128
133
|
const chartOptions = {
|
|
@@ -286,9 +291,11 @@ const VisualChart = ({ item, isDemo = false, isWidgetOrder }) => {
|
|
|
286
291
|
return (
|
|
287
292
|
<View style={styles.container}>
|
|
288
293
|
<View style={styles.titleHistory}>
|
|
289
|
-
<
|
|
290
|
-
{
|
|
291
|
-
|
|
294
|
+
<View style={styles.titleView}>
|
|
295
|
+
<Text size={20} semibold color={Colors.Gray9}>
|
|
296
|
+
{item.label}
|
|
297
|
+
</Text>
|
|
298
|
+
</View>
|
|
292
299
|
{canChooseGroup && (
|
|
293
300
|
<ChartAggregationOption
|
|
294
301
|
groupBy={groupBy}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import { Colors } from '../../../configs';
|
|
4
|
+
import { getStatusBarHeight } from '../../../configs/Constants';
|
|
4
5
|
|
|
5
6
|
export default StyleSheet.create({
|
|
6
7
|
wrap: {
|
|
@@ -17,6 +18,6 @@ export default StyleSheet.create({
|
|
|
17
18
|
marginRight: 22,
|
|
18
19
|
},
|
|
19
20
|
styleScrollView: {
|
|
20
|
-
marginTop:
|
|
21
|
+
marginTop: getStatusBarHeight(),
|
|
21
22
|
},
|
|
22
23
|
});
|
|
@@ -20,15 +20,15 @@ import {
|
|
|
20
20
|
import { axiosPost } from '../../utils/Apis/axios';
|
|
21
21
|
import { AccessibilityLabel } from '../../configs/Constants';
|
|
22
22
|
import Text from '../../commons/Text';
|
|
23
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
23
24
|
|
|
24
|
-
const
|
|
25
|
+
const SharingInviteMembers = ({ route }) => {
|
|
25
26
|
const t = useTranslations();
|
|
26
27
|
const navigation = useNavigation();
|
|
27
28
|
const { unit, permissions } = route?.params || {};
|
|
28
29
|
const [errorText, setErrorText] = useState('');
|
|
29
30
|
const [content, setContent] = useState('');
|
|
30
31
|
const [users, setUsers] = useState([]);
|
|
31
|
-
|
|
32
32
|
const sharePermissions = useCallback(
|
|
33
33
|
async (phone, email) => {
|
|
34
34
|
Keyboard.dismiss();
|
|
@@ -44,9 +44,12 @@ const SelectUser = ({ route }) => {
|
|
|
44
44
|
unit: unit.id,
|
|
45
45
|
permissions,
|
|
46
46
|
});
|
|
47
|
-
|
|
47
|
+
if (success) {
|
|
48
|
+
ToastBottomHelper.success(t('invited_user', { user: phone || email }));
|
|
49
|
+
setUsers([...users, data.user]);
|
|
50
|
+
}
|
|
48
51
|
},
|
|
49
|
-
[users, unit.id, permissions]
|
|
52
|
+
[users, unit.id, permissions, t]
|
|
50
53
|
);
|
|
51
54
|
|
|
52
55
|
const validate = useCallback(() => {
|
|
@@ -145,7 +148,7 @@ const SelectUser = ({ route }) => {
|
|
|
145
148
|
</View>
|
|
146
149
|
</TouchableWithoutFeedback>
|
|
147
150
|
<ViewButtonBottom
|
|
148
|
-
leftTitle={t('
|
|
151
|
+
leftTitle={t('back')}
|
|
149
152
|
onLeftClick={() => navigation.goBack()}
|
|
150
153
|
rightTitle={t('done')}
|
|
151
154
|
rightDisabled={false}
|
|
@@ -217,4 +220,4 @@ const styles = StyleSheet.create({
|
|
|
217
220
|
},
|
|
218
221
|
});
|
|
219
222
|
|
|
220
|
-
export default
|
|
223
|
+
export default SharingInviteMembers;
|
|
@@ -15,7 +15,7 @@ import { AccessibilityLabel } from '../../configs/Constants';
|
|
|
15
15
|
|
|
16
16
|
let dataStationTemp = [];
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const SharingSelectPermission = ({ route }) => {
|
|
19
19
|
const t = useTranslations();
|
|
20
20
|
const { unit, type = '', member } = route?.params || {};
|
|
21
21
|
const navigation = useNavigation();
|
|
@@ -389,6 +389,8 @@ const SelectPermission = ({ route }) => {
|
|
|
389
389
|
{t('no_data')}
|
|
390
390
|
</Text>
|
|
391
391
|
)}
|
|
392
|
+
</View>
|
|
393
|
+
<View style={styles.wrapViewButtonStyle}>
|
|
392
394
|
<ViewButtonBottom
|
|
393
395
|
accessibilityLabelPrefix={
|
|
394
396
|
AccessibilityLabel.PREFIX.SHARING_SELECT_PERMISSION
|
|
@@ -404,4 +406,4 @@ const SelectPermission = ({ route }) => {
|
|
|
404
406
|
);
|
|
405
407
|
};
|
|
406
408
|
|
|
407
|
-
export default memo(
|
|
409
|
+
export default memo(SharingSelectPermission);
|
|
@@ -2,7 +2,6 @@ import React from 'react';
|
|
|
2
2
|
import { create, act } from 'react-test-renderer';
|
|
3
3
|
import MockAdapter from 'axios-mock-adapter';
|
|
4
4
|
|
|
5
|
-
import SelectUser from '../SelectUser';
|
|
6
5
|
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
7
6
|
import { ViewButtonBottom, Button } from '../../../commons';
|
|
8
7
|
import _TextInput from '../../../commons/Form/TextInput';
|
|
@@ -12,10 +11,12 @@ import { getTranslate } from '../../../utils/I18n';
|
|
|
12
11
|
import { SCProvider } from '../../../context';
|
|
13
12
|
import { mockSCStore } from '../../../context/mockStore';
|
|
14
13
|
import api from '../../../utils/Apis/axios';
|
|
14
|
+
import { Text } from 'react-native';
|
|
15
|
+
import SharingInviteMembers from '../SelectUser';
|
|
15
16
|
|
|
16
17
|
const wrapComponent = (route) => (
|
|
17
18
|
<SCProvider initState={mockSCStore({})}>
|
|
18
|
-
<
|
|
19
|
+
<SharingInviteMembers route={route} />
|
|
19
20
|
</SCProvider>
|
|
20
21
|
);
|
|
21
22
|
|
|
@@ -41,7 +42,7 @@ jest.mock('@react-navigation/native', () => {
|
|
|
41
42
|
};
|
|
42
43
|
});
|
|
43
44
|
|
|
44
|
-
describe('test
|
|
45
|
+
describe('test SharingInviteMembers container', () => {
|
|
45
46
|
let tree;
|
|
46
47
|
let route;
|
|
47
48
|
|
|
@@ -91,7 +92,7 @@ describe('test SelectUser container', () => {
|
|
|
91
92
|
const instance = tree.root;
|
|
92
93
|
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
93
94
|
expect(viewButtonBottom.props.leftTitle).toEqual(
|
|
94
|
-
getTranslate('en', '
|
|
95
|
+
getTranslate('en', 'back')
|
|
95
96
|
);
|
|
96
97
|
expect(viewButtonBottom.props.rightTitle).toEqual(
|
|
97
98
|
getTranslate('en', 'done')
|
|
@@ -174,5 +175,46 @@ describe('test SelectUser container', () => {
|
|
|
174
175
|
await button.props.onPress();
|
|
175
176
|
});
|
|
176
177
|
expect(accountList[0].props.accounts).toHaveLength(1);
|
|
178
|
+
|
|
179
|
+
await act(async () => {
|
|
180
|
+
await textInput.props.onChange('0909123456'); // In case you have invited and then intentionally invite again
|
|
181
|
+
});
|
|
182
|
+
mock.onPost(API.SHARE.SHARE()).reply(400);
|
|
183
|
+
await act(async () => {
|
|
184
|
+
await button.props.onPress();
|
|
185
|
+
});
|
|
186
|
+
expect(accountList[0].props.accounts).toHaveLength(1);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('_TextInput onChange email, validated and call api sharedPermission', async () => {
|
|
190
|
+
await act(async () => {
|
|
191
|
+
tree = await create(wrapComponent(route));
|
|
192
|
+
});
|
|
193
|
+
const instance = tree.root;
|
|
194
|
+
const textInput = instance.findByType(_TextInput);
|
|
195
|
+
const button = instance.findByType(Button);
|
|
196
|
+
let accountList = instance.findAllByType(AccountList);
|
|
197
|
+
expect(accountList).toHaveLength(0);
|
|
198
|
+
await act(async () => {
|
|
199
|
+
await textInput.props.onChange('test@eoh.io');
|
|
200
|
+
});
|
|
201
|
+
mock.onPost(API.SHARE.SHARE()).reply(200, {
|
|
202
|
+
user: {
|
|
203
|
+
id: 3,
|
|
204
|
+
name: 'user add',
|
|
205
|
+
phone_number: '',
|
|
206
|
+
email: 'test@eoh.io',
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
await act(async () => {
|
|
210
|
+
await button.props.onPress();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const textPhone = instance.findAll(
|
|
214
|
+
(el) =>
|
|
215
|
+
el.props.accessibilityLabel ===
|
|
216
|
+
AccessibilityLabel.TEXT_PHONE_NUMBER_ITEM && el.type === Text
|
|
217
|
+
);
|
|
218
|
+
expect(textPhone).toHaveLength(0);
|
|
177
219
|
});
|
|
178
220
|
});
|
package/src/screens/Sharing/__test__/{SelectPermission.test.js → SharingSelectPermission.test.js}
RENAMED
|
@@ -3,14 +3,13 @@ import React, { useState } from 'react';
|
|
|
3
3
|
import { FlatList, Text, Platform } from 'react-native';
|
|
4
4
|
import { create } from 'react-test-renderer';
|
|
5
5
|
import MockAdapter from 'axios-mock-adapter';
|
|
6
|
-
|
|
7
|
-
import SelectPermission from '../SelectPermission';
|
|
8
6
|
import { DeviceItem, TitleCheckBox } from '../Components';
|
|
9
7
|
import { ViewButtonBottom } from '../../../commons';
|
|
10
8
|
import { SCProvider } from '../../../context';
|
|
11
9
|
import { mockSCStore } from '../../../context/mockStore';
|
|
12
10
|
import API from '../../../configs/API';
|
|
13
11
|
import api from '../../../utils/Apis/axios';
|
|
12
|
+
import SharingSelectPermission from '../SharingSelectPermission';
|
|
14
13
|
|
|
15
14
|
const mock = new MockAdapter(api.axiosInstance);
|
|
16
15
|
|
|
@@ -37,11 +36,11 @@ jest.mock('@react-navigation/native', () => {
|
|
|
37
36
|
|
|
38
37
|
const wrapComponent = (route) => (
|
|
39
38
|
<SCProvider initState={mockSCStore({})}>
|
|
40
|
-
<
|
|
39
|
+
<SharingSelectPermission route={route} />
|
|
41
40
|
</SCProvider>
|
|
42
41
|
);
|
|
43
42
|
|
|
44
|
-
describe('Test
|
|
43
|
+
describe('Test SharingSelectPermission', () => {
|
|
45
44
|
let tree;
|
|
46
45
|
let route = { params: { unit: { id: 1, name: 'unit 1' } } };
|
|
47
46
|
let listDevices = [
|
|
@@ -242,7 +241,7 @@ describe('Test SelectPermission', () => {
|
|
|
242
241
|
expect(mockGoBack).toBeCalled();
|
|
243
242
|
});
|
|
244
243
|
|
|
245
|
-
it('test
|
|
244
|
+
it('test SharingSelectPermission type share_device', async () => {
|
|
246
245
|
mocSetdata();
|
|
247
246
|
useState.mockImplementationOnce((init) => [true, mockSetState]);
|
|
248
247
|
const response = {
|
|
@@ -95,6 +95,7 @@ export default {
|
|
|
95
95
|
text_new_unit: 'Địa điểm',
|
|
96
96
|
text_sub_units: 'Khu vực',
|
|
97
97
|
is_below: 'dưới',
|
|
98
|
+
is: 'bằng',
|
|
98
99
|
is_above: 'trên',
|
|
99
100
|
edit_actions_list: 'Chỉnh sửa danh sách hành động',
|
|
100
101
|
des_edit_actions_list:
|
|
@@ -1458,4 +1459,6 @@ export default {
|
|
|
1458
1459
|
'customize...': 'Tùy chỉnh...',
|
|
1459
1460
|
uri_invalid: 'URI không hợp lệ',
|
|
1460
1461
|
when_value_is: 'Khi giá trị là',
|
|
1462
|
+
template_not_supported: '"{template}" chưa được hỗ trợ',
|
|
1463
|
+
invited_user: 'Đã mời người dùng {user}',
|
|
1461
1464
|
};
|