react-nativejestjsenzymeplatformplatform-specific

React-Native + Enzyme + Jest: How to test platform specific behaviour?


TLDR: How can I tell my Enzyme / Jest test it should run the tests as if it was running on iOS? I want to test platform specific behaviour.

I'm building a custom status bar component that adds 20 pixels of height, if it runs on iOS to prevent my content from overlapping with the status bar. (Yes, I know React-Navigation has a SafeAreaView, but this only works for iPhone X, not for e.g. iPad.)

Here is my component:

import React from "react";
import { StatusBar as ReactNativeStatusBar, View } from "react-native";

import styles from "./styles";

const StatusBar = ({ props }) => (
  <View style={styles.container}>
    <ReactNativeStatusBar {...props} />
  </View>
);

export default StatusBar;

Here is the styles.js file:

import { StyleSheet, Platform } from "react-native";

const height = Platform.OS === "ios" ? 20 : 0;

const styles = StyleSheet.create({
  container: {
    height: height
  }
});

export default styles;

And here are the tests so far:

import React from "react";
import { shallow } from "enzyme";
import { View } from "react-native";

import StatusBar from "./StatusBar";

const createTestProps = props => ({
  ...props
});

describe("StatusBar", () => {
  describe("rendering", () => {
    let wrapper;
    let props;
    beforeEach(() => {
      props = createTestProps();
      wrapper = shallow(<StatusBar {...props} />);
    });

    it("should render a <View />", () => {
      expect(wrapper.find(View)).toHaveLength(1);
    });

    it("should give the <View /> the container style", () => {
      expect(wrapper.find(View)).toHaveLength(1);
    });

    it("should render a <StatusBar />", () => {
      expect(wrapper.find("StatusBar")).toHaveLength(1);
    });
  });
});

Now what I would like to do is add two more describe areas that explicitly test for the height to be either 20 on iOS or 0 or Android. The problem is I couldn't find how to emulate the platform with Enzyme / Jest tests.

So how do I tell my test suite that it should run the code for the respective platform?


Solution

  • You can override the RN Platform object and perform different tests for each platform. Here's an example for how a test file would like like:

    describe('tests', () => {
    
        let Platform;
        beforeEach(() => {
            Platform = require('react-native').Platform;
        });
    
        describe('ios tests', () => {
            beforeEach(() => {
                Platform.OS = 'ios';
            });
    
            it('should test something on iOS', () => {
    
            });
        });
    
        describe('android tests', () => {
            beforeEach(() => {
                Platform.OS = 'android';
            });
    
            it('should test something on Android', () => {
    
            });
        });
    
    });
    

    By the way, regardless of the question about testing, setting the status-bar height to 20 on iOS is wrong since it can have different sizes on different devices (iPhone X for example)