-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
1,485 additions
and
576 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ node_modules/ | |
# Generated | ||
build/ | ||
dist/ | ||
*.tgz | ||
|
||
# VSCode | ||
.vscode/ | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,11 @@ | |
"engines": { | ||
"node": ">=18" | ||
}, | ||
"files": [ | ||
"dist/", | ||
"src/", | ||
"register.js" | ||
], | ||
"scripts": { | ||
"build": "tsc -p tsconfig.prod.json", | ||
"check": "yarn compile && yarn lint && yarn test", | ||
|
@@ -25,28 +30,41 @@ | |
"test": "NODE_ENV=test mocha" | ||
}, | ||
"packageManager": "[email protected]", | ||
"dependencies": { | ||
"@babel/core": "^7.23.9", | ||
"@babel/preset-react": "^7.23.3", | ||
"@babel/register": "^7.23.7", | ||
"@react-native/babel-preset": "^0.73.20", | ||
"babel-plugin-module-resolver": "^5.0.0", | ||
"dot-prop-immutable": "^2.1.1" | ||
}, | ||
"devDependencies": { | ||
"@assertive-ts/core": "^2.0.0", | ||
"@types/eslint": "^8", | ||
"@testing-library/react-native": "^12.4.3", | ||
"@types/babel__core": "^7.20.5", | ||
"@types/babel__register": "^7.17.3", | ||
"@types/eslint": "^8.56.2", | ||
"@types/mocha": "^10.0.6", | ||
"@types/node": "^20.10.6", | ||
"@types/react": "^18", | ||
"@types/sinon": "^17.0.2", | ||
"@typescript-eslint/eslint-plugin": "^6.17.0", | ||
"@typescript-eslint/parser": "^6.17.0", | ||
"@types/node": "^20.11.7", | ||
"@types/react": "^18.2.48", | ||
"@types/react-test-renderer": "^18.0.7", | ||
"@types/sinon": "^17.0.3", | ||
"@typescript-eslint/eslint-plugin": "^6.19.1", | ||
"@typescript-eslint/parser": "^6.19.1", | ||
"eslint": "^8.56.0", | ||
"eslint-import-resolver-typescript": "^3.6.1", | ||
"eslint-plugin-etc": "^2.0.3", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-jsdoc": "^47.0.2", | ||
"eslint-plugin-jsdoc": "^48.0.4", | ||
"eslint-plugin-sonarjs": "^0.23.0", | ||
"mocha": "^10.2.0", | ||
"react": "18.2.0", | ||
"react-native": "^0.73.1", | ||
"react-native": "^0.73.2", | ||
"react-test-renderer": "^18.2.0", | ||
"sinon": "^17.0.1", | ||
"ts-node": "^10.9.2", | ||
"tslib": "^2.6.2", | ||
"typedoc": "^0.25.6", | ||
"typedoc": "^0.25.7", | ||
"typedoc-plugin-markdown": "^3.17.1", | ||
"typedoc-plugin-merge-modules": "^5.1.0", | ||
"typescript": "^5.3.3" | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const start = Date.now(); | ||
require("./dist/main"); | ||
|
||
const end = Date.now(); | ||
const diff = (end - start) / 1000; | ||
|
||
// eslint-disable-next-line no-console | ||
console.info(`React Native testing mocks registered! (${diff}s)`); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
import path from "path"; | ||
|
||
/** | ||
* A simple no-operation function | ||
*/ | ||
export function noop(): void { | ||
// do nothing... | ||
} | ||
|
||
/** | ||
* Replaces a module with a given `exports` value or another module path. | ||
* | ||
* @param modulePath the path to the module | ||
* @param other the exports to replace or another module path | ||
*/ | ||
export function replace<T>(modulePath: string, other: T | string): void { | ||
const exports = typeof other === "string" | ||
? require(other) as T | ||
: other; | ||
const id = resolveId(modulePath); | ||
|
||
require.cache[id] = { | ||
children: [], | ||
exports, | ||
filename: id, | ||
id, | ||
isPreloading: false, | ||
loaded: true, | ||
parent: require.main, | ||
path: path.dirname(id), | ||
paths: [], | ||
require, | ||
}; | ||
} | ||
|
||
function resolveId(modulePath: string): string { | ||
try { | ||
return require.resolve(modulePath); | ||
} catch (error) { | ||
const hastePath = require.resolve(`${modulePath}.ios`); | ||
return hastePath.slice(0, -4); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { get } from "dot-prop-immutable"; | ||
import { | ||
Component, | ||
ComponentClass, | ||
PropsWithChildren, | ||
ReactNode, | ||
createElement, | ||
} from "react"; | ||
|
||
export function mockComponent<P, C extends ComponentClass<PropsWithChildren<P>>>( | ||
RealComponent: C, | ||
instanceMethods?: object | null, | ||
): C { | ||
const SuperClass: ComponentClass<PropsWithChildren<P>> = typeof RealComponent === "function" | ||
? RealComponent | ||
: Component; | ||
const name = RealComponent.displayName | ||
|| RealComponent.name | ||
|| get(RealComponent, "render.displayName", "") | ||
|| get(RealComponent, "render.name", "") | ||
|| "Unknown"; | ||
const nameWithoutPrefix = name.replace(/^(RCT|RK)/, ""); | ||
|
||
class Mock extends SuperClass { | ||
|
||
public static displayName = "Component"; | ||
|
||
public render(): ReactNode { | ||
const props = { ...RealComponent.defaultProps }; | ||
|
||
if (this.props) { | ||
Object.keys(this.props).forEach(key => { | ||
// We can't just assign props on top of defaultProps | ||
// because React treats undefined as special and different from null. | ||
// If a prop is specified but set to undefined it is ignored and the | ||
// default prop is used instead. If it is set to null, then the | ||
// null value overwrites the default value. | ||
|
||
const prop: unknown = get(this.props, key); | ||
|
||
if (prop !== undefined) { | ||
Object.assign(props, { [key]: prop }); | ||
} | ||
}); | ||
} | ||
|
||
return createElement(nameWithoutPrefix, props, this.props.children); | ||
} | ||
} | ||
|
||
Mock.displayName = nameWithoutPrefix; | ||
|
||
Object.keys(RealComponent).forEach(key => { | ||
const staticProp: unknown = get(RealComponent, key); | ||
|
||
if (staticProp !== undefined) { | ||
Object.assign(Mock, { [key]: staticProp }); | ||
} | ||
}); | ||
|
||
if (instanceMethods) { | ||
Object.assign(Component.prototype, instanceMethods); | ||
} | ||
|
||
return Mock as unknown as C; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { get } from "dot-prop-immutable"; | ||
import { Component, ComponentClass, PropsWithChildren, ReactNode } from "react"; | ||
|
||
export function mockModal<P, C extends typeof Component<P>>(Base: C): C { | ||
const BaseComponent = Base as ComponentClass<PropsWithChildren<P>>; | ||
|
||
class Mock extends BaseComponent { | ||
|
||
public render(): ReactNode { | ||
if (get(this.props, "visible") === false) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<BaseComponent {...this.props}> | ||
{this.props.children} | ||
</BaseComponent> | ||
); | ||
} | ||
} | ||
|
||
return Mock as C; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { Component, ComponentClass, PropsWithChildren, ReactNode, createElement } from "react"; | ||
|
||
const native = { tag: 1 }; | ||
|
||
export function mockNativeComponent(viewName: string): ComponentClass { | ||
return class extends Component<PropsWithChildren<unknown>> { | ||
|
||
public static displayName = viewName === "RCTView" ? "View" : viewName; | ||
|
||
protected _nativeTag = native.tag++; | ||
|
||
public constructor(props: PropsWithChildren<unknown>) { | ||
super(props); | ||
} | ||
|
||
public render(): ReactNode { | ||
return createElement(viewName, this.props, this.props.children); | ||
} | ||
|
||
public blur(): void { /* noop */ } | ||
public focus(): void { /* noop */ } | ||
public measure(): void { /* noop */ } | ||
public measureInWindow(): void { /* noop */ } | ||
public measureLayout(): void { /* noop */ } | ||
public setNativeProps(): void { /* noop */ } | ||
}; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { noop } from "./commons"; | ||
|
||
export const MockNativeMethods = { | ||
blur: noop, | ||
focus: noop, | ||
measure: noop, | ||
measureInWindow: noop, | ||
measureLayout: noop, | ||
setNativeProps: noop, | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* eslint-disable sort-keys */ | ||
import { noop } from "../../helpers/commons"; | ||
|
||
export const AccessibilityInfoMock = { | ||
addEventListener: noop, | ||
announceForAccessibility: noop, | ||
isAccessibilityServiceEnabled: noop, | ||
isBoldTextEnabled: noop, | ||
isGrayscaleEnabled: noop, | ||
isInvertColorsEnabled: noop, | ||
isReduceMotionEnabled: noop, | ||
prefersCrossFadeTransitions: noop, | ||
isReduceTransparencyEnabled: noop, | ||
isScreenReaderEnabled: (): Promise<boolean> => Promise.resolve(false), | ||
setAccessibilityFocus: noop, | ||
sendAccessibilityEvent: noop, | ||
getRecommendedTimeoutMillis: noop, | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { ActivityIndicator } from "react-native"; | ||
|
||
import { mockComponent } from "../../helpers/mockComponent"; | ||
|
||
export const ActivityIndicatorMock = mockComponent(ActivityIndicator, null); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { NativeEventSubscription } from "react-native"; | ||
|
||
import { noop } from "../../helpers/commons"; | ||
|
||
export const AppStateMock = { | ||
addEventListener: (): NativeEventSubscription => ({ remove: noop }), | ||
currentState: noop, | ||
removeEventListener: noop, | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { noop } from "../../helpers/commons"; | ||
|
||
export const ClipboardMock = { | ||
getString: (): string => "", | ||
setString: noop, | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ComponentClass } from "react"; | ||
import { Image } from "react-native"; | ||
|
||
import { noop } from "../../helpers/commons"; | ||
import { mockComponent } from "../../helpers/mockComponent"; | ||
|
||
const Mock = mockComponent(Image as ComponentClass); | ||
|
||
export const ImageMock = Object.assign(Mock, { | ||
getSize: noop, | ||
getSizeWithHeaders: noop, | ||
prefetch: noop, | ||
prefetchWithMetadata: noop, | ||
queryCache: noop, | ||
resolveAssetSource: noop, | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { noop } from "../../helpers/commons"; | ||
|
||
export const LinkingMock = { | ||
addEventListener: noop, | ||
canOpenURL: (): Promise<boolean> => Promise.resolve(true), | ||
getInitialURL: (): Promise<void> => Promise.resolve(), | ||
openSettings: noop, | ||
openURL: noop, | ||
sendIntent: noop, | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Modal } from "react-native"; | ||
|
||
import { mockComponent } from "../../helpers/mockComponent"; | ||
import { mockModal } from "../../helpers/mockModal"; | ||
|
||
const BaseMock = mockComponent(Modal); | ||
|
||
export const ModalMock = mockModal(BaseMock); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Component, ReactNode, createElement } from "react"; | ||
import { requireNativeComponent } from "react-native"; | ||
|
||
const RCTRefreshControl = requireNativeComponent("RCTRefreshControl"); | ||
|
||
export class RefreshControlMock extends Component { | ||
|
||
public static latestRef?: RefreshControlMock; | ||
|
||
public componentDidMount(): void { | ||
RefreshControlMock.latestRef = this; | ||
} | ||
|
||
public render(): ReactNode { | ||
return createElement(RCTRefreshControl); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* eslint-disable sort-keys */ | ||
import { PropsWithChildren, ReactNode, createElement } from "react"; | ||
import { ScrollView, View, requireNativeComponent } from "react-native"; | ||
|
||
import { noop } from "../../helpers/commons"; | ||
import { mockComponent } from "../../helpers/mockComponent"; | ||
import { MockNativeMethods } from "../../helpers/mockNativeMethods"; | ||
|
||
const RCTScrollView = requireNativeComponent("RCTScrollView"); | ||
const BaseMock = mockComponent(ScrollView, { | ||
...MockNativeMethods, | ||
getScrollResponder: noop, | ||
getScrollableNode: noop, | ||
getInnerViewNode: noop, | ||
getInnerViewRef: noop, | ||
getNativeScrollRef: noop, | ||
scrollTo: noop, | ||
scrollToEnd: noop, | ||
flashScrollIndicators: noop, | ||
scrollResponderZoomTo: noop, | ||
scrollResponderScrollNativeHandleToKeyboard: noop, | ||
}); | ||
|
||
export class ScrollViewMock<P> extends BaseMock { | ||
|
||
public constructor(props: PropsWithChildren<P>) { | ||
super(props); | ||
} | ||
|
||
public render(): ReactNode { | ||
return createElement( | ||
RCTScrollView, | ||
this.props as object, | ||
this.props.refreshControl, | ||
createElement(mockComponent(View), {}, this.props.children), | ||
); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { Text } from "react-native"; | ||
|
||
import { mockComponent } from "../../helpers/mockComponent"; | ||
import { MockNativeMethods } from "../../helpers/mockNativeMethods"; | ||
|
||
export const TextMock = mockComponent(Text, MockNativeMethods); |
Oops, something went wrong.