Aure77
Aure77

Reputation: 3209

How to mock react-native Platform.OS with Jest?

Jest runner use "ios" as default OS (Plaform.OS) for react-native tests. How to do test in jest that have platform dependent code. An further more, how to mock static constant imported in a module.

Here is the code: utils.ts:

import { Platform } from "react-native";
export const isIOS = Platform.OS === "ios"; // note constant, not function

items.ts:

import { isIOS } from "@my/utils";
export const items = [{
    id: 1,
    name: isIOS ? "Apple" : "Android"
}]

test:

import { items } from "./items";

// not working because Platform.OS is used statically during import statement
it("should be android", () => {
  Platform.OS = "android"; // too late...
  expect(items[0].name).toBe("Android"); // fail: Apple
}

it("should be ios", () => {
  Platform.OS = "ios";
  expect(items[0].name).toBe("Apple"); // works due to default platform value in Jest
}

I saw some workaround using jest.resetModules() & require inside test/it block (and change Plaform.OS before require) but does exist a more simple way to achieve that ?

Upvotes: 1

Views: 3256

Answers (3)

octobus
octobus

Reputation: 1276

In my code I have created a new constant called CustomPlatform.

So in my code instead of Platform from react-native. I use CustomPlatform from @/constants

import { Platform } from 'react-native'


const CustomPlatform = {
  IS_IOS: Platform.OS === 'ios',
}

The code:

const permissionType = Platform.IS_IOS ? PERMISSIONS.IOS.CAMERA : PERMISSIONS.ANDROID.CAMERA

and then I can just use jest.replaceProperty(Platform, 'IS_IOS', false)

and with this approach I could also cover the android. But be aware in after this change you might want to revert this change at the end of the test otherwise it may affect other tests.

Upvotes: 0

bartosss
bartosss

Reputation: 1038

Simply replacing the iOS implementation with the Android implementation works. Use the other way around for Android.

    jest.mock('react-native/Libraries/Utilities/Platform.ios.js', () => ({
      ...jest.requireActual(
        'react-native/Libraries/Utilities/Platform.android.js',
      ),
    }));

Upvotes: 0

Artem Golendukhin
Artem Golendukhin

Reputation: 214

In your test file

import { Platform } from 'react-native'

jest.doMock('react-native/Libraries/Utilities/Platform.android.js', () => ({
  OS: 'android',
  select: jest.fn(),
}))

jest.doMock('react-native/Libraries/Utilities/Platform.ios.js', () => ({
  OS: 'android',
  select: jest.fn(),
}))

describe('Platform', () => {
  it('Should be android', () => {
    expect(Platform.OS).toEqual('android')
  })

  it('Should be ios', () => {
    Platform.OS = 'ios'
    expect(Platform.OS).toEqual('ios')
  })

  it('Should be android', () => {
    Platform.OS = 'android'
    expect(Platform.OS).toEqual('android')
  })
})

Upvotes: 3

Related Questions