import { Platform as PlatformExpo } from '@unimodules/core'; import { Linking, Platform } from 'react-native'; import { EventEmitter } from 'fbemitter'; const allOriginalPropertyDescriptors = new Map(); export function mockProperty(object, property, mockValue) { // Save a reference to the original property descriptor if (!allOriginalPropertyDescriptors.has(object)) { allOriginalPropertyDescriptors.set(object, new Map()); } let descriptor = Object.getOwnPropertyDescriptor(object, property); allOriginalPropertyDescriptors.get(object).set(property, descriptor); // Select fields to inherit from the original descriptor if (descriptor) { let { configurable, enumerable, writable } = descriptor; descriptor = { configurable, enumerable, writable }; } Object.defineProperty(object, property, { configurable: true, enumerable: true, writable: true, ...descriptor, value: mockValue, }); } export function unmockProperty(object, property) { let descriptors = allOriginalPropertyDescriptors.get(object); if (!descriptors || !descriptors.has(property)) { return; } let descriptor = descriptors.get(property); if (descriptor) { Object.defineProperty(object, property, descriptor); } else { delete object[property]; } // Clean up the reference descriptors.delete(property); if (!descriptors.size) { allOriginalPropertyDescriptors.delete(object); } } export function unmockAllProperties() { for (let [object, descriptors] of allOriginalPropertyDescriptors) { for (let [property, descriptor] of descriptors) { if (descriptor) { Object.defineProperty(object, property, descriptor); } else { delete object[property]; } } } allOriginalPropertyDescriptors.clear(); } export function mockPlatformIOS() { mockProperty(Platform, 'OS', 'ios'); mockProperty(PlatformExpo, 'OS', 'ios'); } export function mockPlatformAndroid() { mockProperty(Platform, 'OS', 'android'); mockProperty(PlatformExpo, 'OS', 'android'); } export function mockPlatformWeb() { mockProperty(Platform, 'OS', 'web'); mockProperty(PlatformExpo, 'OS', 'web'); } export function describeCrossPlatform(message, tests) { describe(` ${message}`, () => { beforeEach(mockPlatformIOS); tests(); afterAll(() => { unmockProperty(Platform, 'OS'); unmockProperty(PlatformExpo, 'OS'); }); }); describe(`🤖 ${message}`, () => { beforeEach(mockPlatformAndroid); tests(); afterAll(() => { unmockProperty(Platform, 'OS'); unmockProperty(PlatformExpo, 'OS'); }); }); } export function mockLinking() { let emitter = new EventEmitter(); let subscriptions = {}; mockProperty( Linking, 'addEventListener', jest.fn((type, cb) => { let subscription = emitter.addListener(type, cb); subscriptions[type] = subscriptions[type] || new Map(); subscriptions[type].set(cb, subscription); }) ); mockProperty( Linking, 'removeEventListener', jest.fn((type, cb) => { subscriptions[type].delete(cb); }) ); return (type, data) => { emitter.emit(type, data); }; }