@umituz/react-native-design-system 2.3.1 → 2.3.2
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 +15 -3
- package/src/atoms/AtomicInput.tsx +0 -1
- package/src/atoms/AtomicPicker.tsx +0 -1
- package/src/atoms/picker/components/PickerChips.tsx +0 -1
- package/src/atoms/picker/components/PickerModal.tsx +1 -3
- package/src/atoms/picker/styles/pickerStyles.ts +1 -1
- package/src/device/domain/entities/Device.ts +207 -0
- package/src/device/domain/entities/DeviceMemoryUtils.ts +62 -0
- package/src/device/domain/entities/DeviceTypeUtils.ts +66 -0
- package/src/device/domain/entities/__tests__/DeviceMemoryUtils.test.ts +118 -0
- package/src/device/domain/entities/__tests__/DeviceTypeUtils.test.ts +104 -0
- package/src/device/domain/entities/__tests__/DeviceUtils.test.ts +167 -0
- package/src/device/index.ts +51 -0
- package/src/device/infrastructure/services/ApplicationInfoService.ts +86 -0
- package/src/device/infrastructure/services/DeviceCapabilityService.ts +60 -0
- package/src/device/infrastructure/services/DeviceIdService.ts +70 -0
- package/src/device/infrastructure/services/DeviceInfoService.ts +95 -0
- package/src/device/infrastructure/services/DeviceService.ts +104 -0
- package/src/device/infrastructure/services/PersistentDeviceIdService.ts +132 -0
- package/src/device/infrastructure/services/UserFriendlyIdService.ts +68 -0
- package/src/device/infrastructure/utils/__tests__/nativeModuleUtils.test.ts +158 -0
- package/src/device/infrastructure/utils/__tests__/stringUtils.test.ts +120 -0
- package/src/device/infrastructure/utils/nativeModuleUtils.ts +69 -0
- package/src/device/infrastructure/utils/stringUtils.ts +59 -0
- package/src/device/presentation/hooks/useAnonymousUser.ts +117 -0
- package/src/device/presentation/hooks/useDeviceInfo.ts +222 -0
- package/src/molecules/ConfirmationModalContent.tsx +4 -4
- package/src/molecules/ConfirmationModalMain.tsx +1 -1
- package/src/molecules/ScreenHeader.tsx +2 -2
- package/src/molecules/confirmation-modal/components.tsx +1 -1
- package/src/molecules/confirmation-modal/styles/confirmationModalStyles.ts +6 -7
- package/src/presentation/utils/variants/__tests__/core.test.ts +0 -1
- package/src/responsive/deviceDetection.ts +5 -5
- package/src/responsive/iPadBreakpoints.ts +55 -0
- package/src/responsive/iPadDetection.ts +48 -0
- package/src/responsive/iPadLayoutUtils.ts +95 -0
- package/src/responsive/iPadModalUtils.ts +98 -0
- package/src/responsive/index.ts +31 -0
- package/src/safe-area/__tests__/components/SafeAreaProvider.test.tsx +2 -2
- package/src/safe-area/__tests__/hooks/useContentSafeAreaPadding.test.tsx +2 -2
- package/src/safe-area/__tests__/hooks/useHeaderSafeAreaPadding.test.tsx +2 -2
- package/src/safe-area/__tests__/hooks/useSafeAreaInsets.test.tsx +2 -2
- package/src/safe-area/__tests__/hooks/useStatusBarSafeAreaPadding.test.tsx +2 -2
- package/src/safe-area/__tests__/integration/completeFlow.test.tsx +5 -4
- package/src/safe-area/__tests__/utils/testUtils.tsx +5 -4
- package/src/theme/infrastructure/stores/themeStore.ts +0 -2
- package/src/typography/presentation/utils/textColorUtils.ts +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"./typography": "./src/typography/index.ts",
|
|
19
19
|
"./responsive": "./src/responsive/index.ts",
|
|
20
20
|
"./safe-area": "./src/safe-area/index.ts",
|
|
21
|
+
"./device": "./src/device/index.ts",
|
|
21
22
|
"./package.json": "./package.json"
|
|
22
23
|
},
|
|
23
24
|
"scripts": {
|
|
@@ -60,7 +61,9 @@
|
|
|
60
61
|
"react-native-reanimated": ">=3.16.0",
|
|
61
62
|
"react-native-safe-area-context": ">=5.0.0",
|
|
62
63
|
"react-native-svg": ">=15.0.0",
|
|
63
|
-
"zustand": ">=5.0.0"
|
|
64
|
+
"zustand": ">=5.0.0",
|
|
65
|
+
"expo-device": ">=5.0.0",
|
|
66
|
+
"expo-application": ">=5.0.0"
|
|
64
67
|
},
|
|
65
68
|
"peerDependenciesMeta": {
|
|
66
69
|
"expo-linear-gradient": {
|
|
@@ -71,6 +74,12 @@
|
|
|
71
74
|
},
|
|
72
75
|
"@gorhom/bottom-sheet": {
|
|
73
76
|
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"expo-device": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"expo-application": {
|
|
82
|
+
"optional": true
|
|
74
83
|
}
|
|
75
84
|
},
|
|
76
85
|
"devDependencies": {
|
|
@@ -95,7 +104,10 @@
|
|
|
95
104
|
"react-native-safe-area-context": "^5.6.0",
|
|
96
105
|
"react-native-svg": "15.12.1",
|
|
97
106
|
"typescript": "~5.9.2",
|
|
98
|
-
"zustand": "^5.0.2"
|
|
107
|
+
"zustand": "^5.0.2",
|
|
108
|
+
"expo-device": "~7.0.2",
|
|
109
|
+
"expo-application": "~5.9.1",
|
|
110
|
+
"expo-localization": "~16.0.1"
|
|
99
111
|
},
|
|
100
112
|
"publishConfig": {
|
|
101
113
|
"access": "public"
|
|
@@ -59,7 +59,6 @@ interface PickerModalProps {
|
|
|
59
59
|
export const PickerModal: React.FC<PickerModalProps> = React.memo(({
|
|
60
60
|
visible,
|
|
61
61
|
onClose,
|
|
62
|
-
options: _options,
|
|
63
62
|
selectedValues,
|
|
64
63
|
onSelect,
|
|
65
64
|
title,
|
|
@@ -67,7 +66,6 @@ export const PickerModal: React.FC<PickerModalProps> = React.memo(({
|
|
|
67
66
|
searchQuery,
|
|
68
67
|
onSearchChange,
|
|
69
68
|
filteredOptions,
|
|
70
|
-
multiple: _multiple = false,
|
|
71
69
|
emptyMessage = 'No options available',
|
|
72
70
|
searchPlaceholder = 'Search...',
|
|
73
71
|
closeAccessibilityLabel = 'Close picker',
|
|
@@ -76,7 +74,7 @@ export const PickerModal: React.FC<PickerModalProps> = React.memo(({
|
|
|
76
74
|
const tokens = useAppDesignTokens();
|
|
77
75
|
const insets = useSafeAreaInsets();
|
|
78
76
|
|
|
79
|
-
const modalOverlayStyles = getModalOverlayStyles(
|
|
77
|
+
const modalOverlayStyles = getModalOverlayStyles();
|
|
80
78
|
const modalContainerStyles = getModalContainerStyles(tokens, 0);
|
|
81
79
|
const modalHeaderStyles = getModalHeaderStyles(tokens);
|
|
82
80
|
const modalTitleStyles = getModalTitleStyles(tokens);
|
|
@@ -110,7 +110,7 @@ export const getPickerErrorStyles = (tokens: DesignTokens): TextStyle => ({
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
// Modal styles
|
|
113
|
-
export const getModalOverlayStyles = (
|
|
113
|
+
export const getModalOverlayStyles = (): ViewStyle => ({
|
|
114
114
|
flex: 1,
|
|
115
115
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
116
116
|
justifyContent: 'flex-end',
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Domain - Core Entities
|
|
3
|
+
*
|
|
4
|
+
* This file defines core types and interfaces for device information.
|
|
5
|
+
* Handles device details, app info using expo-device and expo-application.
|
|
6
|
+
*
|
|
7
|
+
* @domain device
|
|
8
|
+
* @layer domain/entities
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type * as DeviceModule from 'expo-device';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Re-export Device types from expo-device
|
|
15
|
+
*/
|
|
16
|
+
export type DeviceType = DeviceModule.DeviceType;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Device information interface
|
|
20
|
+
*/
|
|
21
|
+
export interface DeviceInfo {
|
|
22
|
+
// Device identification
|
|
23
|
+
brand: string | null;
|
|
24
|
+
manufacturer: string | null;
|
|
25
|
+
modelName: string | null;
|
|
26
|
+
modelId: string | null;
|
|
27
|
+
deviceName: string | null;
|
|
28
|
+
deviceYearClass: number | null;
|
|
29
|
+
|
|
30
|
+
// Device type
|
|
31
|
+
deviceType: DeviceType | null;
|
|
32
|
+
isDevice: boolean;
|
|
33
|
+
|
|
34
|
+
// OS information
|
|
35
|
+
osName: string | null;
|
|
36
|
+
osVersion: string | null;
|
|
37
|
+
osBuildId: string | null;
|
|
38
|
+
platformApiLevel: number | null;
|
|
39
|
+
|
|
40
|
+
// Memory
|
|
41
|
+
totalMemory: number | null;
|
|
42
|
+
|
|
43
|
+
// Platform
|
|
44
|
+
platform: 'ios' | 'android' | 'web';
|
|
45
|
+
|
|
46
|
+
// Localization
|
|
47
|
+
timezone: string | null;
|
|
48
|
+
region: string | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Application information interface
|
|
53
|
+
*/
|
|
54
|
+
export interface ApplicationInfo {
|
|
55
|
+
// App identification
|
|
56
|
+
applicationName: string;
|
|
57
|
+
applicationId: string;
|
|
58
|
+
nativeApplicationVersion: string | null;
|
|
59
|
+
nativeBuildVersion: string | null;
|
|
60
|
+
|
|
61
|
+
// Installation
|
|
62
|
+
installTime: Date | null;
|
|
63
|
+
lastUpdateTime: Date | null;
|
|
64
|
+
|
|
65
|
+
// Platform-specific
|
|
66
|
+
androidId: string | null; // Android only
|
|
67
|
+
iosIdForVendor: string | null; // iOS only
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Combined device and app info
|
|
72
|
+
*/
|
|
73
|
+
export interface SystemInfo {
|
|
74
|
+
device: DeviceInfo;
|
|
75
|
+
application: ApplicationInfo;
|
|
76
|
+
timestamp: number;
|
|
77
|
+
userId?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Device constants
|
|
82
|
+
*/
|
|
83
|
+
export const DEVICE_CONSTANTS = {
|
|
84
|
+
DEVICE_TYPE: {
|
|
85
|
+
UNKNOWN: 0,
|
|
86
|
+
PHONE: 1,
|
|
87
|
+
TABLET: 2,
|
|
88
|
+
DESKTOP: 3,
|
|
89
|
+
TV: 4,
|
|
90
|
+
},
|
|
91
|
+
PLATFORM: {
|
|
92
|
+
IOS: 'ios',
|
|
93
|
+
ANDROID: 'android',
|
|
94
|
+
WEB: 'web',
|
|
95
|
+
},
|
|
96
|
+
} as const;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Device utilities
|
|
100
|
+
*/
|
|
101
|
+
export class DeviceUtils {
|
|
102
|
+
/**
|
|
103
|
+
* Check if running on physical device (not simulator/emulator)
|
|
104
|
+
*/
|
|
105
|
+
static isPhysicalDevice(isDevice: boolean): boolean {
|
|
106
|
+
return isDevice;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get device display name
|
|
111
|
+
*/
|
|
112
|
+
static getDeviceDisplayName(info: DeviceInfo): string {
|
|
113
|
+
if (info.deviceName) {
|
|
114
|
+
return info.deviceName;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (info.modelName) {
|
|
118
|
+
return info.modelName;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (info.brand && info.manufacturer) {
|
|
122
|
+
return `${info.brand} ${info.manufacturer}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return 'Unknown Device';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get OS display string
|
|
130
|
+
*/
|
|
131
|
+
static getOSDisplayString(info: DeviceInfo): string {
|
|
132
|
+
if (info.osName && info.osVersion) {
|
|
133
|
+
return `${info.osName} ${info.osVersion}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (info.osName) {
|
|
137
|
+
return info.osName;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return 'Unknown OS';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get app version string
|
|
145
|
+
*/
|
|
146
|
+
static getAppVersionString(info: ApplicationInfo): string {
|
|
147
|
+
if (info.nativeApplicationVersion && info.nativeBuildVersion) {
|
|
148
|
+
return `${info.nativeApplicationVersion} (${info.nativeBuildVersion})`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (info.nativeApplicationVersion) {
|
|
152
|
+
return info.nativeApplicationVersion;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return 'Unknown Version';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Check if device meets minimum requirements
|
|
160
|
+
*/
|
|
161
|
+
static meetsMinimumRequirements(info: DeviceInfo, minMemoryGB: number = 1): {
|
|
162
|
+
meets: boolean;
|
|
163
|
+
reasons: string[];
|
|
164
|
+
} {
|
|
165
|
+
const reasons: string[] = [];
|
|
166
|
+
|
|
167
|
+
if (!info.isDevice) {
|
|
168
|
+
reasons.push('Running on simulator/emulator');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (info.totalMemory) {
|
|
172
|
+
const memoryGB = info.totalMemory / (1024 * 1024 * 1024);
|
|
173
|
+
if (memoryGB < minMemoryGB) {
|
|
174
|
+
reasons.push(`Insufficient memory: ${memoryGB.toFixed(2)}GB (minimum: ${minMemoryGB}GB)`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (info.deviceYearClass && info.deviceYearClass < 2018) {
|
|
179
|
+
reasons.push(`Device too old: ${info.deviceYearClass} (minimum: 2018)`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
meets: reasons.length === 0,
|
|
184
|
+
reasons,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get device tier (low/mid/high) based on specs
|
|
190
|
+
*/
|
|
191
|
+
static getDeviceTier(info: DeviceInfo): 'low' | 'mid' | 'high' {
|
|
192
|
+
if (info.deviceYearClass) {
|
|
193
|
+
if (info.deviceYearClass >= 2022) return 'high';
|
|
194
|
+
if (info.deviceYearClass >= 2019) return 'mid';
|
|
195
|
+
return 'low';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (info.totalMemory) {
|
|
199
|
+
const memoryGB = info.totalMemory / (1024 * 1024 * 1024);
|
|
200
|
+
if (memoryGB >= 6) return 'high';
|
|
201
|
+
if (memoryGB >= 3) return 'mid';
|
|
202
|
+
return 'low';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return 'mid';
|
|
206
|
+
}
|
|
207
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Memory Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for device memory calculations and formatting
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Device memory utilities
|
|
9
|
+
*/
|
|
10
|
+
export class DeviceMemoryUtils {
|
|
11
|
+
/**
|
|
12
|
+
* Convert bytes to gigabytes
|
|
13
|
+
*/
|
|
14
|
+
static bytesToGB(bytes: number): number {
|
|
15
|
+
return bytes / (1024 * 1024 * 1024);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Convert bytes to megabytes
|
|
20
|
+
*/
|
|
21
|
+
static bytesToMB(bytes: number): number {
|
|
22
|
+
return bytes / (1024 * 1024);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Format memory size to human readable string
|
|
27
|
+
*/
|
|
28
|
+
static formatMemorySize(bytes: number | null): string {
|
|
29
|
+
if (!bytes) return 'Unknown';
|
|
30
|
+
|
|
31
|
+
const gb = this.bytesToGB(bytes);
|
|
32
|
+
if (gb >= 1) {
|
|
33
|
+
return `${gb.toFixed(2)} GB`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const mb = this.bytesToMB(bytes);
|
|
37
|
+
return `${mb.toFixed(2)} MB`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if memory is sufficient for requirements
|
|
42
|
+
*/
|
|
43
|
+
static hasSufficientMemory(
|
|
44
|
+
totalMemory: number | null,
|
|
45
|
+
requiredGB: number
|
|
46
|
+
): boolean {
|
|
47
|
+
if (!totalMemory) return false;
|
|
48
|
+
return this.bytesToGB(totalMemory) >= requiredGB;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get memory tier classification
|
|
53
|
+
*/
|
|
54
|
+
static getMemoryTier(totalMemory: number | null): 'low' | 'mid' | 'high' {
|
|
55
|
+
if (!totalMemory) return 'mid';
|
|
56
|
+
|
|
57
|
+
const gb = this.bytesToGB(totalMemory);
|
|
58
|
+
if (gb >= 6) return 'high';
|
|
59
|
+
if (gb >= 3) return 'mid';
|
|
60
|
+
return 'low';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Type Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for device type detection
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DeviceType } from './Device';
|
|
8
|
+
import { DEVICE_CONSTANTS } from './Device';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Device type utilities
|
|
12
|
+
*/
|
|
13
|
+
export class DeviceTypeUtils {
|
|
14
|
+
/**
|
|
15
|
+
* Check if device is a tablet
|
|
16
|
+
*/
|
|
17
|
+
static isTablet(deviceType: DeviceType | null): boolean {
|
|
18
|
+
return deviceType === DEVICE_CONSTANTS.DEVICE_TYPE.TABLET;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if device is a phone
|
|
23
|
+
*/
|
|
24
|
+
static isPhone(deviceType: DeviceType | null): boolean {
|
|
25
|
+
return deviceType === DEVICE_CONSTANTS.DEVICE_TYPE.PHONE;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check if device is desktop
|
|
30
|
+
*/
|
|
31
|
+
static isDesktop(deviceType: DeviceType | null): boolean {
|
|
32
|
+
return deviceType === DEVICE_CONSTANTS.DEVICE_TYPE.DESKTOP;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if device is TV
|
|
37
|
+
*/
|
|
38
|
+
static isTV(deviceType: DeviceType | null): boolean {
|
|
39
|
+
return deviceType === DEVICE_CONSTANTS.DEVICE_TYPE.TV;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if device type is unknown
|
|
44
|
+
*/
|
|
45
|
+
static isUnknown(deviceType: DeviceType | null): boolean {
|
|
46
|
+
return deviceType === DEVICE_CONSTANTS.DEVICE_TYPE.UNKNOWN;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get device type name
|
|
51
|
+
*/
|
|
52
|
+
static getDeviceTypeName(deviceType: DeviceType | null): string {
|
|
53
|
+
switch (deviceType) {
|
|
54
|
+
case DEVICE_CONSTANTS.DEVICE_TYPE.PHONE:
|
|
55
|
+
return 'Phone';
|
|
56
|
+
case DEVICE_CONSTANTS.DEVICE_TYPE.TABLET:
|
|
57
|
+
return 'Tablet';
|
|
58
|
+
case DEVICE_CONSTANTS.DEVICE_TYPE.DESKTOP:
|
|
59
|
+
return 'Desktop';
|
|
60
|
+
case DEVICE_CONSTANTS.DEVICE_TYPE.TV:
|
|
61
|
+
return 'TV';
|
|
62
|
+
default:
|
|
63
|
+
return 'Unknown';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Memory Utils Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { DeviceMemoryUtils } from '../DeviceMemoryUtils';
|
|
6
|
+
|
|
7
|
+
describe('DeviceMemoryUtils', () => {
|
|
8
|
+
describe('bytesToGB', () => {
|
|
9
|
+
it('should convert bytes to gigabytes', () => {
|
|
10
|
+
const bytes = 6442450944; // 6GB
|
|
11
|
+
const result = DeviceMemoryUtils.bytesToGB(bytes);
|
|
12
|
+
expect(result).toBe(6);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should handle decimal values', () => {
|
|
16
|
+
const bytes = 3221225472; // 3GB
|
|
17
|
+
const result = DeviceMemoryUtils.bytesToGB(bytes);
|
|
18
|
+
expect(result).toBe(3);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('bytesToMB', () => {
|
|
23
|
+
it('should convert bytes to megabytes', () => {
|
|
24
|
+
const bytes = 1048576; // 1MB
|
|
25
|
+
const result = DeviceMemoryUtils.bytesToMB(bytes);
|
|
26
|
+
expect(result).toBe(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should handle larger values', () => {
|
|
30
|
+
const bytes = 6442450944; // 6GB = 6144MB
|
|
31
|
+
const result = DeviceMemoryUtils.bytesToMB(bytes);
|
|
32
|
+
expect(result).toBe(6144);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('formatMemorySize', () => {
|
|
37
|
+
it('should format bytes in GB when >= 1GB', () => {
|
|
38
|
+
const bytes = 6442450944; // 6GB
|
|
39
|
+
const result = DeviceMemoryUtils.formatMemorySize(bytes);
|
|
40
|
+
expect(result).toBe('6.00 GB');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should format bytes in MB when < 1GB', () => {
|
|
44
|
+
const bytes = 524288000; // ~500MB
|
|
45
|
+
const result = DeviceMemoryUtils.formatMemorySize(bytes);
|
|
46
|
+
expect(result).toBe('500.00 MB');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should return Unknown for null bytes', () => {
|
|
50
|
+
const result = DeviceMemoryUtils.formatMemorySize(null);
|
|
51
|
+
expect(result).toBe('Unknown');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should format with 2 decimal places', () => {
|
|
55
|
+
const bytes = 15032385536; // 14GB
|
|
56
|
+
const result = DeviceMemoryUtils.formatMemorySize(bytes);
|
|
57
|
+
expect(result).toBe('14.00 GB');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('hasSufficientMemory', () => {
|
|
62
|
+
it('should return true when memory is sufficient', () => {
|
|
63
|
+
const totalMemory = 6442450944; // 6GB
|
|
64
|
+
const result = DeviceMemoryUtils.hasSufficientMemory(totalMemory, 4);
|
|
65
|
+
expect(result).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return false when memory is insufficient', () => {
|
|
69
|
+
const totalMemory = 2147483648; // 2GB
|
|
70
|
+
const result = DeviceMemoryUtils.hasSufficientMemory(totalMemory, 4);
|
|
71
|
+
expect(result).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should return false for null memory', () => {
|
|
75
|
+
const result = DeviceMemoryUtils.hasSufficientMemory(null, 4);
|
|
76
|
+
expect(result).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle exact match', () => {
|
|
80
|
+
const totalMemory = 4294967296; // 4GB
|
|
81
|
+
const result = DeviceMemoryUtils.hasSufficientMemory(totalMemory, 4);
|
|
82
|
+
expect(result).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('getMemoryTier', () => {
|
|
87
|
+
it('should return high for >= 6GB', () => {
|
|
88
|
+
const totalMemory = 6442450944; // 6GB
|
|
89
|
+
const result = DeviceMemoryUtils.getMemoryTier(totalMemory);
|
|
90
|
+
expect(result).toBe('high');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should return mid for >= 3GB and < 6GB', () => {
|
|
94
|
+
const totalMemory = 4294967296; // 4GB
|
|
95
|
+
const result = DeviceMemoryUtils.getMemoryTier(totalMemory);
|
|
96
|
+
expect(result).toBe('mid');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should return low for < 3GB', () => {
|
|
100
|
+
const totalMemory = 2147483648; // 2GB
|
|
101
|
+
const result = DeviceMemoryUtils.getMemoryTier(totalMemory);
|
|
102
|
+
expect(result).toBe('low');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should return mid for null memory', () => {
|
|
106
|
+
const result = DeviceMemoryUtils.getMemoryTier(null);
|
|
107
|
+
expect(result).toBe('mid');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should handle boundary values', () => {
|
|
111
|
+
const exactly3GB = 3221225472; // 3GB
|
|
112
|
+
const exactly6GB = 6442450944; // 6GB
|
|
113
|
+
|
|
114
|
+
expect(DeviceMemoryUtils.getMemoryTier(exactly3GB)).toBe('mid');
|
|
115
|
+
expect(DeviceMemoryUtils.getMemoryTier(exactly6GB)).toBe('high');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Type Utils Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { DeviceTypeUtils } from '../DeviceTypeUtils';
|
|
6
|
+
import { DEVICE_CONSTANTS } from '../Device';
|
|
7
|
+
|
|
8
|
+
describe('DeviceTypeUtils', () => {
|
|
9
|
+
describe('isTablet', () => {
|
|
10
|
+
it('should return true for tablet device', () => {
|
|
11
|
+
expect(DeviceTypeUtils.isTablet(DEVICE_CONSTANTS.DEVICE_TYPE.TABLET)).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should return false for phone device', () => {
|
|
15
|
+
expect(DeviceTypeUtils.isTablet(DEVICE_CONSTANTS.DEVICE_TYPE.PHONE)).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return false for null device type', () => {
|
|
19
|
+
expect(DeviceTypeUtils.isTablet(null)).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('isPhone', () => {
|
|
24
|
+
it('should return true for phone device', () => {
|
|
25
|
+
expect(DeviceTypeUtils.isPhone(DEVICE_CONSTANTS.DEVICE_TYPE.PHONE)).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should return false for tablet device', () => {
|
|
29
|
+
expect(DeviceTypeUtils.isPhone(DEVICE_CONSTANTS.DEVICE_TYPE.TABLET)).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return false for null device type', () => {
|
|
33
|
+
expect(DeviceTypeUtils.isPhone(null)).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('isDesktop', () => {
|
|
38
|
+
it('should return true for desktop device', () => {
|
|
39
|
+
expect(DeviceTypeUtils.isDesktop(DEVICE_CONSTANTS.DEVICE_TYPE.DESKTOP)).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should return false for phone device', () => {
|
|
43
|
+
expect(DeviceTypeUtils.isDesktop(DEVICE_CONSTANTS.DEVICE_TYPE.PHONE)).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should return false for null device type', () => {
|
|
47
|
+
expect(DeviceTypeUtils.isDesktop(null)).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('isTV', () => {
|
|
52
|
+
it('should return true for TV device', () => {
|
|
53
|
+
expect(DeviceTypeUtils.isTV(DEVICE_CONSTANTS.DEVICE_TYPE.TV)).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should return false for phone device', () => {
|
|
57
|
+
expect(DeviceTypeUtils.isTV(DEVICE_CONSTANTS.DEVICE_TYPE.PHONE)).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should return false for null device type', () => {
|
|
61
|
+
expect(DeviceTypeUtils.isTV(null)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('isUnknown', () => {
|
|
66
|
+
it('should return true for unknown device', () => {
|
|
67
|
+
expect(DeviceTypeUtils.isUnknown(DEVICE_CONSTANTS.DEVICE_TYPE.UNKNOWN)).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should return false for phone device', () => {
|
|
71
|
+
expect(DeviceTypeUtils.isUnknown(DEVICE_CONSTANTS.DEVICE_TYPE.PHONE)).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should return false for null device type', () => {
|
|
75
|
+
expect(DeviceTypeUtils.isUnknown(null)).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('getDeviceTypeName', () => {
|
|
80
|
+
it('should return Phone for phone device', () => {
|
|
81
|
+
expect(DeviceTypeUtils.getDeviceTypeName(DEVICE_CONSTANTS.DEVICE_TYPE.PHONE)).toBe('Phone');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should return Tablet for tablet device', () => {
|
|
85
|
+
expect(DeviceTypeUtils.getDeviceTypeName(DEVICE_CONSTANTS.DEVICE_TYPE.TABLET)).toBe('Tablet');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should return Desktop for desktop device', () => {
|
|
89
|
+
expect(DeviceTypeUtils.getDeviceTypeName(DEVICE_CONSTANTS.DEVICE_TYPE.DESKTOP)).toBe('Desktop');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should return TV for TV device', () => {
|
|
93
|
+
expect(DeviceTypeUtils.getDeviceTypeName(DEVICE_CONSTANTS.DEVICE_TYPE.TV)).toBe('TV');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should return Unknown for unknown device', () => {
|
|
97
|
+
expect(DeviceTypeUtils.getDeviceTypeName(DEVICE_CONSTANTS.DEVICE_TYPE.UNKNOWN)).toBe('Unknown');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should return Unknown for null device type', () => {
|
|
101
|
+
expect(DeviceTypeUtils.getDeviceTypeName(null)).toBe('Unknown');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|