Created
February 15, 2024 16:43
-
-
Save Doko-Demo-Doa/74995f3701e1e1db2237ad033bdc0b37 to your computer and use it in GitHub Desktop.
Sample Jest setup file with mocking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/react-navigation/react-navigation/issues/9727 | |
jest.useFakeTimers(); | |
import "@testing-library/jest-native/extend-expect"; | |
import "react-native-gesture-handler/jestSetup"; | |
import type { | |
UnistylesBreakpoints, | |
UnistylesThemes, | |
} from "react-native-unistyles"; | |
import type { | |
ColorSchemeName, | |
UnistylesBridge, | |
} from "react-native-unistyles/lib/typescript/src/types"; | |
jest.mock("react-native-reanimated", () => | |
require("react-native-reanimated/mock"), | |
); | |
// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing | |
jest.mock("react-native/Libraries/Animated/NativeAnimatedHelper"); | |
// react-native-theme-switch-animation | |
jest.mock("react-native-theme-switch-animation", () => jest.fn()); | |
jest.mock("react-native-bootsplash", () => { | |
return { | |
hide: jest.fn().mockResolvedValue(undefined), | |
isVisible: jest.fn().mockResolvedValue(false), | |
useHideAnimation: jest.fn().mockReturnValue({ | |
container: {}, | |
logo: { source: 0 }, | |
brand: { source: 0 }, | |
}), | |
}; | |
}); | |
// Ignore yellow logbox | |
console = { | |
...console, | |
log: jest.fn(), | |
warn: jest.fn(), | |
}; | |
jest.mock("react-native/Libraries/EventEmitter/NativeEventEmitter"); | |
// Unistyles complete mock | |
jest.mock("react-native", () => { | |
const RN = jest.requireActual("react-native"); | |
class MockUnistylesBridge { | |
#timerRef?: ReturnType<typeof setTimeout> = undefined; | |
#hasAdaptiveThemes = false; | |
#supportsAutomaticColorScheme = false; | |
#screenWidth = 375; | |
#screenHeight = 812; | |
#themes: Array<keyof UnistylesThemes> = []; | |
#breakpoints: UnistylesBreakpoints = {} as UnistylesBreakpoints; | |
#colorScheme: ColorSchemeName = "light"; | |
#themeName: keyof UnistylesThemes = "" as keyof UnistylesThemes; | |
#enabledPlugins: Array<string> = []; | |
#unistylesEvents = new RN.NativeEventEmitter(RN.NativeModules.Unistyles); | |
#sortedBreakpointPairs: Array<[keyof UnistylesBreakpoints, number]> = []; | |
#breakpoint: keyof UnistylesBreakpoints = "" as keyof UnistylesBreakpoints; | |
#contentSizeCategory = "unspecified"; | |
public install() { | |
// @ts-ignore | |
global.__UNISTYLES__ = this; | |
return true; | |
} | |
public useTheme(themeName: keyof UnistylesThemes) { | |
this.#themeName = themeName; | |
this.emitThemeChange(); | |
} | |
public updateTheme(themeName: keyof UnistylesThemes) { | |
if (this.#themeName === themeName) { | |
this.emitThemeChange(); | |
} | |
} | |
public useBreakpoints(breakpoints: UnistylesBreakpoints) { | |
this.#breakpoints = breakpoints; | |
this.#sortedBreakpointPairs = Object.entries(breakpoints).sort( | |
([, a], [, b]) => (a ?? 0) - (b ?? 0), | |
) as Array<[keyof UnistylesBreakpoints, number]>; | |
this.#breakpoint = this.getBreakpointFromScreenWidth( | |
this.#screenWidth as number, | |
); | |
} | |
public useAdaptiveThemes(enable: boolean) { | |
this.#hasAdaptiveThemes = enable; | |
if (!this.#hasAdaptiveThemes || !this.#supportsAutomaticColorScheme) | |
return; | |
if (this.#themeName !== this.#colorScheme) { | |
this.#themeName = this.#colorScheme as keyof UnistylesThemes; | |
this.emitThemeChange(); | |
} | |
} | |
public addPlugin(pluginName: string, notify: boolean) { | |
this.#enabledPlugins = [pluginName].concat(this.#enabledPlugins); | |
if (notify) this.emitPluginChange(); | |
} | |
public removePlugin(pluginName: string) { | |
this.#enabledPlugins = this.#enabledPlugins.filter( | |
(name) => name !== pluginName, | |
); | |
this.emitPluginChange(); | |
} | |
get themeName(): keyof UnistylesThemes { | |
// biome-ignore lint/style/noNonNullAssertion: <explanation> | |
if (this.#themes.length === 1) return this.#themes.at(0)!; | |
return this.#themeName; | |
} | |
// set themeName(themeName: keyof UnistylesThemes) { | |
// this.#themeName = themeName as keyof UnistylesThemes; | |
// this.emitThemeChange(); | |
// } | |
set themes(themes: Array<keyof UnistylesThemes>) { | |
this.#themes = themes; | |
this.#supportsAutomaticColorScheme = | |
themes.includes("light") && themes.includes("dark"); | |
} | |
get screenWidth() { | |
return this.#screenWidth; | |
} | |
get screenHeight() { | |
return this.#screenHeight; | |
} | |
// biome-ignore lint/suspicious/noExplicitAny: <explanation> | |
get contentSizeCategory(): any { | |
return this.#contentSizeCategory; | |
} | |
get breakpoint() { | |
return this.#breakpoint || undefined; | |
} | |
get breakpoints() { | |
return this.#breakpoints; | |
} | |
get hasAdaptiveThemes() { | |
return this.#hasAdaptiveThemes; | |
} | |
get sortedBreakpointPairs() { | |
return this.#sortedBreakpointPairs; | |
} | |
get enabledPlugins() { | |
return this.#enabledPlugins; | |
} | |
get colorScheme() { | |
return this.#colorScheme; | |
} | |
private emitPluginChange() { | |
this.#unistylesEvents.emit("__unistylesOnChange", { type: "plugin" }); | |
} | |
private emitThemeChange() { | |
this.#unistylesEvents.emit("__unistylesOnChange", { | |
type: "theme", | |
payload: { themeName: this.#themeName }, | |
}); | |
} | |
private getBreakpointFromScreenWidth( | |
width: number, | |
): keyof UnistylesBreakpoints { | |
const breakpoint = this.#sortedBreakpointPairs.find( | |
([, value], index, otherBreakpoints) => { | |
const minVal = value; | |
const maxVal = otherBreakpoints[index + 1]?.[1]; | |
if (!maxVal) return true; | |
return width >= minVal && width < maxVal; | |
}, | |
); | |
return breakpoint?.at(0) as keyof UnistylesBreakpoints; | |
} | |
} | |
if (!RN.NativeModules.Unistyles) | |
RN.NativeModules.Unistyles = | |
new MockUnistylesBridge() satisfies UnistylesBridge; | |
return RN; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment