Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/workflows/react-native-cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,22 @@ jobs:
yarn install --frozen-lockfile

- name: 📋 Create Google Json File
if: ${{ matrix.platform == 'android' }}
run: |
echo $UNIT_GOOGLE_SERVICES | base64 -d > google-services.json

- name: 📋 Update package.json Versions
run: |
# Check if jq is installed, if not install it
if ! command -v jq &> /dev/null; then
# Ensure jq exists on both Linux and macOS
if ! command -v jq >/dev/null 2>&1; then
echo "Installing jq..."
sudo apt-get update && sudo apt-get install -y jq
if [[ "$RUNNER_OS" == "Linux" ]]; then
sudo apt-get update && sudo apt-get install -y jq
elif [[ "$RUNNER_OS" == "macOS" ]]; then
brew update && brew install jq
else
echo "Unsupported OS for auto-install of jq" >&2; exit 1
fi
fi

# Fix the main entry in package.json
Expand Down
36 changes: 36 additions & 0 deletions __mocks__/expo-av.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Mock for expo-av
export const Audio = {
setAudioModeAsync: jest.fn().mockResolvedValue(undefined),
Sound: class MockSound {
static createAsync = jest.fn().mockResolvedValue({
sound: new this(),
status: { isLoaded: true },
});

playAsync = jest.fn().mockResolvedValue({ status: { isPlaying: true } });
stopAsync = jest.fn().mockResolvedValue({ status: { isPlaying: false } });
unloadAsync = jest.fn().mockResolvedValue(undefined);
setVolumeAsync = jest.fn().mockResolvedValue(undefined);
},
setIsEnabledAsync: jest.fn().mockResolvedValue(undefined),
getPermissionsAsync: jest.fn().mockResolvedValue({
granted: true,
canAskAgain: true,
expires: 'never',
status: 'granted',
}),
requestPermissionsAsync: jest.fn().mockResolvedValue({
granted: true,
canAskAgain: true,
expires: 'never',
status: 'granted',
}),
};

export const InterruptionModeIOS = {
MixWithOthers: 0,
DoNotMix: 1,
DuckOthers: 2,
};

export const AVPlaybackSource = {};
Empty file added __mocks__/expo-constants.ts
Empty file.
31 changes: 31 additions & 0 deletions __mocks__/expo-device.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export const isDevice = true;
export const deviceName = 'Test Device';
export const deviceYearClass = 2023;
export const totalMemory = 8192;
export const supportedCpuArchitectures = ['arm64'];
export const osName = 'iOS';
export const osVersion = '15.0';
export const platformApiLevel = null;
export const modelName = 'iPhone 13';
export const modelId = 'iPhone14,5';
export const designName = 'iPhone';
export const productName = 'iPhone';
export const deviceType = 1;
export const manufacturer = 'Apple';

export default {
isDevice,
deviceName,
deviceYearClass,
totalMemory,
supportedCpuArchitectures,
osName,
osVersion,
platformApiLevel,
modelName,
modelId,
designName,
productName,
deviceType,
manufacturer,
};
68 changes: 68 additions & 0 deletions __mocks__/expo-location.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const LocationAccuracy = {
Lowest: 1,
Low: 2,
Balanced: 3,
High: 4,
Highest: 5,
BestForNavigation: 6,
};

export const LocationActivityType = {
Other: 1,
AutomotiveNavigation: 2,
Fitness: 3,
OtherNavigation: 4,
Airborne: 5,
};

export const requestForegroundPermissionsAsync = jest.fn().mockResolvedValue({
status: 'granted',
granted: true,
canAskAgain: true,
expires: 'never',
});

export const requestBackgroundPermissionsAsync = jest.fn().mockResolvedValue({
status: 'granted',
granted: true,
canAskAgain: true,
expires: 'never',
});

export const getCurrentPositionAsync = jest.fn().mockResolvedValue({
coords: {
latitude: 40.7128,
longitude: -74.006,
altitude: null,
accuracy: 5,
altitudeAccuracy: null,
heading: null,
speed: null,
},
timestamp: Date.now(),
});

export const watchPositionAsync = jest.fn().mockImplementation((options, callback) => {
const interval = setInterval(() => {
callback({
coords: {
latitude: 40.7128,
longitude: -74.006,
altitude: null,
accuracy: 5,
altitudeAccuracy: null,
heading: 0,
speed: null,
},
timestamp: Date.now(),
});
}, 1000);

return Promise.resolve({
remove: () => clearInterval(interval),
});
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.

export const startLocationUpdatesAsync = jest.fn().mockResolvedValue(undefined);
export const stopLocationUpdatesAsync = jest.fn().mockResolvedValue(undefined);
export const hasStartedLocationUpdatesAsync = jest.fn().mockResolvedValue(false);
10 changes: 10 additions & 0 deletions __mocks__/expo-navigation-bar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const setVisibilityAsync = jest.fn().mockResolvedValue(undefined);
export const getVisibilityAsync = jest.fn().mockResolvedValue('visible');
export const setBackgroundColorAsync = jest.fn().mockResolvedValue(undefined);
export const getBackgroundColorAsync = jest.fn().mockResolvedValue('#000000');
export const setBehaviorAsync = jest.fn().mockResolvedValue(undefined);
export const getBehaviorAsync = jest.fn().mockResolvedValue('overlay-swipe');
export const setButtonStyleAsync = jest.fn().mockResolvedValue(undefined);
export const getButtonStyleAsync = jest.fn().mockResolvedValue('light');
export const setPositionAsync = jest.fn().mockResolvedValue(undefined);
export const getPositionAsync = jest.fn().mockResolvedValue('bottom');
21 changes: 21 additions & 0 deletions __mocks__/expo-task-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const defineTask = jest.fn();
export const startLocationTrackingAsync = jest.fn().mockResolvedValue(undefined);
export const stopLocationTrackingAsync = jest.fn().mockResolvedValue(undefined);
export const hasStartedLocationTrackingAsync = jest.fn().mockResolvedValue(false);
export const getRegisteredTasksAsync = jest.fn().mockResolvedValue([]);
export const isTaskRegisteredAsync = jest.fn().mockResolvedValue(false);
export const unregisterTaskAsync = jest.fn().mockResolvedValue(undefined);
export const unregisterAllTasksAsync = jest.fn().mockResolvedValue(undefined);

const TaskManager = {
defineTask,
startLocationTrackingAsync,
stopLocationTrackingAsync,
hasStartedLocationTrackingAsync,
getRegisteredTasksAsync,
isTaskRegisteredAsync,
unregisterTaskAsync,
unregisterAllTasksAsync,
};

export default TaskManager;
4 changes: 4 additions & 0 deletions __mocks__/react-native-edge-to-edge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const SystemBars = ({ style, hidden }: any) => null;

export const setStatusBarStyle = jest.fn();
export const setNavigationBarStyle = jest.fn();
22 changes: 22 additions & 0 deletions jest-platform-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Platform setup for Jest - must run before other modules
const mockPlatform = {
OS: 'ios' as const,
select: jest.fn().mockImplementation((obj: any) => obj.ios || obj.default),
Version: 17,
constants: {},
isTesting: true,
};

// Set global Platform for testing library - must be set before other imports
Object.defineProperty(global, 'Platform', {
value: mockPlatform,
writable: true,
enumerable: true,
configurable: true,
});

// Also mock the react-native Platform module directly
jest.doMock('react-native/Libraries/Utilities/Platform', () => mockPlatform);

// Ensure Platform is available in the global scope for React Navigation and other libs
(global as any).Platform = mockPlatform;
21 changes: 17 additions & 4 deletions jest-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,23 @@ jest.mock('expo-audio', () => ({
setIsAudioActiveAsync: jest.fn(),
}));

// Mock Platform.OS for React Native
jest.mock('react-native/Libraries/Utilities/Platform', () => ({
OS: 'ios',
select: jest.fn().mockImplementation((obj) => obj.ios || obj.default),
// Mock the host component names function to prevent testing library errors
jest.mock('@testing-library/react-native/build/helpers/host-component-names', () => ({
getHostComponentNames: jest.fn(() => ({
text: 'Text',
view: 'View',
scrollView: 'ScrollView',
touchable: 'TouchableOpacity',
switch: 'Switch',
textInput: 'TextInput',
})),
configureHostComponentNamesIfNeeded: jest.fn(),
isHostText: jest.fn((element) => element?.type === 'Text' || element?._fiber?.type === 'Text' || (typeof element === 'object' && element?.props?.children && typeof element.props.children === 'string')),
isHostTextInput: jest.fn((element) => element?.type === 'TextInput' || element?._fiber?.type === 'TextInput'),
isHostImage: jest.fn((element) => element?.type === 'Image' || element?._fiber?.type === 'Image'),
isHostSwitch: jest.fn((element) => element?.type === 'Switch' || element?._fiber?.type === 'Switch'),
isHostScrollView: jest.fn((element) => element?.type === 'ScrollView' || element?._fiber?.type === 'ScrollView'),
isHostModal: jest.fn((element) => element?.type === 'Modal' || element?._fiber?.type === 'Modal'),
}));

Comment thread
coderabbitai[bot] marked this conversation as resolved.
// Global mocks for common problematic modules
Expand Down
Loading
Loading