@amazon-devices/shopify__react-native-performance-lists-profiler 1.1.1758683737
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.kepler.md +331 -0
- package/README.md +7 -0
- package/ReactNativePerformanceListsProfiler.podspec +30 -0
- package/SystemBundles/1b881d5412b1fc3466fe9ebb1f1c33915d19056d122263f1ba0356a8c71c31ca.bundle +10666 -0
- package/SystemBundles/1b881d5412b1fc3466fe9ebb1f1c33915d19056d122263f1ba0356a8c71c31ca.map +1 -0
- package/SystemModules/amzn__shopify__react-native-performance-lists-profiler-1.modules.txt +26 -0
- package/SystemModules/amzn__shopify__react-native-performance-lists-profiler-1.private.modules.txt +96 -0
- package/SystemModules/keplerscript-system-bundle-config.json +7 -0
- package/THIRD_PARTY_NOTICES.txt +472 -0
- package/android/build.gradle +59 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/kotlin/com/shopify/reactnativeperformancelistsprofiler/BlankAreaView.kt +150 -0
- package/android/src/main/kotlin/com/shopify/reactnativeperformancelistsprofiler/FlashListPerformanceViewManager.kt +49 -0
- package/android/src/main/kotlin/com/shopify/reactnativeperformancelistsprofiler/FlatListPerformanceViewManager.kt +47 -0
- package/android/src/main/kotlin/com/shopify/reactnativeperformancelistsprofiler/ReactNativePerformanceListsProfilerPackage.kt +19 -0
- package/dist/FlashListPerformanceView.d.ts +14 -0
- package/dist/FlashListPerformanceView.d.ts.map +1 -0
- package/dist/FlashListPerformanceView.js +33 -0
- package/dist/FlashListPerformanceView.js.map +1 -0
- package/dist/FlashListPerformanceView.types.d.ts +21 -0
- package/dist/FlashListPerformanceView.types.d.ts.map +1 -0
- package/dist/FlashListPerformanceView.types.js +3 -0
- package/dist/FlashListPerformanceView.types.js.map +1 -0
- package/dist/FlashListPerformanceViewNativeComponent.d.ts +4 -0
- package/dist/FlashListPerformanceViewNativeComponent.d.ts.map +1 -0
- package/dist/FlashListPerformanceViewNativeComponent.js +7 -0
- package/dist/FlashListPerformanceViewNativeComponent.js.map +1 -0
- package/dist/FlashListPerformanceViewNativeComponent.kepler.d.ts +5 -0
- package/dist/FlashListPerformanceViewNativeComponent.kepler.d.ts.map +1 -0
- package/dist/FlashListPerformanceViewNativeComponent.kepler.js +35 -0
- package/dist/FlashListPerformanceViewNativeComponent.kepler.js.map +1 -0
- package/dist/FlatListPerformanceView.d.ts +15 -0
- package/dist/FlatListPerformanceView.d.ts.map +1 -0
- package/dist/FlatListPerformanceView.js +38 -0
- package/dist/FlatListPerformanceView.js.map +1 -0
- package/dist/FlatListPerformanceView.types.d.ts +19 -0
- package/dist/FlatListPerformanceView.types.d.ts.map +1 -0
- package/dist/FlatListPerformanceView.types.js +10 -0
- package/dist/FlatListPerformanceView.types.js.map +1 -0
- package/dist/FlatListPerformanceViewNativeComponent.d.ts +4 -0
- package/dist/FlatListPerformanceViewNativeComponent.d.ts.map +1 -0
- package/dist/FlatListPerformanceViewNativeComponent.js +7 -0
- package/dist/FlatListPerformanceViewNativeComponent.js.map +1 -0
- package/dist/FlatListPerformanceViewNativeComponent.kepler.d.ts +5 -0
- package/dist/FlatListPerformanceViewNativeComponent.kepler.d.ts.map +1 -0
- package/dist/FlatListPerformanceViewNativeComponent.kepler.js +35 -0
- package/dist/FlatListPerformanceViewNativeComponent.kepler.js.map +1 -0
- package/dist/ListsProfiler.d.ts +9 -0
- package/dist/ListsProfiler.d.ts.map +1 -0
- package/dist/ListsProfiler.js +54 -0
- package/dist/ListsProfiler.js.map +1 -0
- package/dist/ListsProfilerContext.d.ts +9 -0
- package/dist/ListsProfilerContext.d.ts.map +1 -0
- package/dist/ListsProfilerContext.js +11 -0
- package/dist/ListsProfilerContext.js.map +1 -0
- package/dist/ListsProfilerModule.d.ts +6 -0
- package/dist/ListsProfilerModule.d.ts.map +1 -0
- package/dist/ListsProfilerModule.js +14 -0
- package/dist/ListsProfilerModule.js.map +1 -0
- package/dist/ListsProfilerProps.d.ts +19 -0
- package/dist/ListsProfilerProps.d.ts.map +1 -0
- package/dist/ListsProfilerProps.js +3 -0
- package/dist/ListsProfilerProps.js.map +1 -0
- package/dist/__tests__/FlashListPerformanceView.test.d.ts +2 -0
- package/dist/__tests__/FlashListPerformanceView.test.d.ts.map +1 -0
- package/dist/__tests__/FlashListPerformanceView.test.js +53 -0
- package/dist/__tests__/FlashListPerformanceView.test.js.map +1 -0
- package/dist/__tests__/FlatListPerformanceView.test.d.ts +2 -0
- package/dist/__tests__/FlatListPerformanceView.test.d.ts.map +1 -0
- package/dist/__tests__/FlatListPerformanceView.test.js +59 -0
- package/dist/__tests__/FlatListPerformanceView.test.js.map +1 -0
- package/dist/__tests__/ListProfiler.test.d.ts +2 -0
- package/dist/__tests__/ListProfiler.test.d.ts.map +1 -0
- package/dist/__tests__/ListProfiler.test.js +53 -0
- package/dist/__tests__/ListProfiler.test.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/ios/ReactNativePerformanceListsProfiler.xcodeproj/project.pbxproj +3 -0
- package/ios/Sources/BlankAreaView.swift +111 -0
- package/ios/Sources/FlashListPerformanceViewManager.m +9 -0
- package/ios/Sources/FlashListPerformanceViewManager.swift +23 -0
- package/ios/Sources/FlatListPerformanceViewManager.m +9 -0
- package/ios/Sources/FlatListPerformanceViewManager.swift +18 -0
- package/ios/Sources/ReactNativePerfomanceListsProfilerUmbrella.h +8 -0
- package/ios/Tests/ReactNativePerformanceListsProfilerTests.swift +5 -0
- package/kepler-compatibility.json +8 -0
- package/kepler-transformed-package-info.json +3 -0
- package/package.json +1 -0
- package/src/FlashListPerformanceView.tsx +44 -0
- package/src/FlashListPerformanceView.types.ts +23 -0
- package/src/FlashListPerformanceViewNativeComponent.kepler.ts +38 -0
- package/src/FlashListPerformanceViewNativeComponent.ts +7 -0
- package/src/FlatListPerformanceView.tsx +61 -0
- package/src/FlatListPerformanceView.types.ts +28 -0
- package/src/FlatListPerformanceViewNativeComponent.kepler.tsx +38 -0
- package/src/FlatListPerformanceViewNativeComponent.tsx +7 -0
- package/src/ListsProfiler.tsx +67 -0
- package/src/ListsProfilerContext.tsx +13 -0
- package/src/ListsProfilerModule.ts +25 -0
- package/src/ListsProfilerProps.ts +18 -0
- package/src/__tests__/FlashListPerformanceView.test.tsx +71 -0
- package/src/__tests__/FlatListPerformanceView.test.tsx +77 -0
- package/src/__tests__/ListProfiler.test.tsx +60 -0
- package/src/__tests__/setupJest.js +5 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, {useRef, useContext, useCallback} from 'react';
|
|
2
|
+
|
|
3
|
+
import {ListsProfilerContext} from './ListsProfilerContext';
|
|
4
|
+
import {FlatListPerformanceViewNativeComponent} from './FlatListPerformanceViewNativeComponent';
|
|
5
|
+
import {OnBlankAreaEvent, OnInteractiveEvent} from './FlatListPerformanceView.types';
|
|
6
|
+
import ListsProfilerProps from './ListsProfilerProps';
|
|
7
|
+
// @amznmod_react - Add import for the turbomodule
|
|
8
|
+
import ListsProfilerModule from './ListsProfilerModule';
|
|
9
|
+
|
|
10
|
+
interface FlatListPerformanceViewProps {
|
|
11
|
+
/**
|
|
12
|
+
* Name of the list. Used for distinguishing between lists in the `ListsProfiler`.
|
|
13
|
+
*/
|
|
14
|
+
listName: string;
|
|
15
|
+
children: JSX.Element;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Wrap your `FlatList` with this component.
|
|
20
|
+
*/
|
|
21
|
+
const FlatListPerformanceView = ({
|
|
22
|
+
children,
|
|
23
|
+
listName,
|
|
24
|
+
onInteractive = () => {},
|
|
25
|
+
onBlankArea = () => {},
|
|
26
|
+
}: FlatListPerformanceViewProps & ListsProfilerProps) => {
|
|
27
|
+
const time = useRef(Date.now()).current;
|
|
28
|
+
const listsProfilerController = useContext(ListsProfilerContext);
|
|
29
|
+
const onInteractiveCallback = useCallback(
|
|
30
|
+
({nativeEvent}: OnInteractiveEvent) => {
|
|
31
|
+
const tti = nativeEvent.timestamp - time;
|
|
32
|
+
onInteractive(tti, listName);
|
|
33
|
+
listsProfilerController.onInteractive(tti, listName);
|
|
34
|
+
},
|
|
35
|
+
[listsProfilerController, onInteractive, listName, time],
|
|
36
|
+
);
|
|
37
|
+
const onBlankAreaCallback = useCallback(
|
|
38
|
+
({nativeEvent}: OnBlankAreaEvent) => {
|
|
39
|
+
onBlankArea(nativeEvent.offsetStart, nativeEvent.offsetEnd, listName);
|
|
40
|
+
listsProfilerController.onBlankArea(nativeEvent.offsetStart, nativeEvent.offsetEnd, listName);
|
|
41
|
+
},
|
|
42
|
+
[onBlankArea, listsProfilerController, listName],
|
|
43
|
+
);
|
|
44
|
+
return (
|
|
45
|
+
<FlatListPerformanceViewNativeComponent
|
|
46
|
+
onInteractive={onInteractiveCallback}
|
|
47
|
+
onBlankAreaEvent={onBlankAreaCallback}
|
|
48
|
+
>
|
|
49
|
+
{/* @amznmod_react - Extend the list's onScroll with a call to the TM */}
|
|
50
|
+
{React.cloneElement(children, {
|
|
51
|
+
onScroll: () => {
|
|
52
|
+
if (children?.props?.onScroll) {
|
|
53
|
+
children.props.onScroll();
|
|
54
|
+
}
|
|
55
|
+
ListsProfilerModule?.invokeCallback();
|
|
56
|
+
},
|
|
57
|
+
})}
|
|
58
|
+
</FlatListPerformanceViewNativeComponent>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
export default FlatListPerformanceView;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* PROPRIETARY/CONFIDENTIAL
|
|
5
|
+
*
|
|
6
|
+
* Use is subject to license terms.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface OnInteractiveEvent {
|
|
10
|
+
nativeEvent: {
|
|
11
|
+
timestamp: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface OnBlankAreaEvent {
|
|
16
|
+
nativeEvent: {
|
|
17
|
+
offsetStart: number;
|
|
18
|
+
offsetEnd: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type OnInteractiveHandler = (event: OnInteractiveEvent) => void;
|
|
23
|
+
type OnBlankAreaEventHandler = (event: OnBlankAreaEvent) => void;
|
|
24
|
+
|
|
25
|
+
export interface FlatListPerformanceViewNativeComponentProps {
|
|
26
|
+
onInteractive: OnInteractiveHandler;
|
|
27
|
+
onBlankAreaEvent: OnBlankAreaEventHandler;
|
|
28
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* PROPRIETARY/CONFIDENTIAL
|
|
5
|
+
*
|
|
6
|
+
* Use is subject to license terms.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
10
|
+
// @ts-ignore For some reason this is unknown
|
|
11
|
+
import register from 'react-native/Libraries/Utilities/registerGeneratedViewConfig';
|
|
12
|
+
import { HostComponent } from 'react-native';
|
|
13
|
+
|
|
14
|
+
import { FlatListPerformanceViewNativeComponentProps } from './FlatListPerformanceView.types';
|
|
15
|
+
|
|
16
|
+
const FlatListPerformanceView = 'AmazonFlatListPerformanceView';
|
|
17
|
+
|
|
18
|
+
register(FlatListPerformanceView, {
|
|
19
|
+
uiViewClassName: FlatListPerformanceView,
|
|
20
|
+
bubblingEventTypes: {
|
|
21
|
+
topOnInteractive: {
|
|
22
|
+
phasedRegistrationNames: {
|
|
23
|
+
bubbled: 'onInteractive',
|
|
24
|
+
captured: 'onInteractiveCapture',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
topOnBlankAreaEvent: {
|
|
28
|
+
phasedRegistrationNames: {
|
|
29
|
+
bubbled: 'onBlankAreaEvent',
|
|
30
|
+
captured: 'onBlankAreaEventCapture',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const FlatListPerformanceViewNativeComponent =
|
|
37
|
+
(FlatListPerformanceView as unknown) as HostComponent<FlatListPerformanceViewNativeComponentProps>;
|
|
38
|
+
export { FlatListPerformanceViewNativeComponent };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import {requireNativeComponent} from 'react-native';
|
|
2
|
+
|
|
3
|
+
import {FlatListPerformanceViewNativeComponentProps} from './FlatListPerformanceView.types';
|
|
4
|
+
|
|
5
|
+
const FlatListPerformanceViewNativeComponent =
|
|
6
|
+
requireNativeComponent<FlatListPerformanceViewNativeComponentProps>('FlatListPerformanceView');
|
|
7
|
+
export {FlatListPerformanceViewNativeComponent};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, {useCallback} from 'react';
|
|
2
|
+
import {Flipper, addPlugin} from 'react-native-flipper';
|
|
3
|
+
|
|
4
|
+
import {ListsProfilerContextProvider} from './ListsProfilerContext';
|
|
5
|
+
import ListsProfilerProps from './ListsProfilerProps';
|
|
6
|
+
|
|
7
|
+
const bootstrapPlugin = (): Promise<Flipper.FlipperConnection> => {
|
|
8
|
+
return new Promise(resolve => {
|
|
9
|
+
addPlugin({
|
|
10
|
+
getId: () => '@shopify/react-native-performance',
|
|
11
|
+
onConnect: connection => {
|
|
12
|
+
return resolve(connection);
|
|
13
|
+
},
|
|
14
|
+
onDisconnect: () => {},
|
|
15
|
+
runInBackground: () => true,
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Wrap your app with this component to get events from all the lists wrapped with their performance view.
|
|
22
|
+
* For example, `FlatList` must be wrapped in the `FlatListPerformanceView`.
|
|
23
|
+
*/
|
|
24
|
+
const ListsProfiler = ({onInteractive = () => {}, onBlankArea = () => {}, children}: ListsProfilerProps) => {
|
|
25
|
+
let connection: Flipper.FlipperConnection | undefined;
|
|
26
|
+
bootstrapPlugin()
|
|
27
|
+
.then(conn => {
|
|
28
|
+
connection = conn;
|
|
29
|
+
})
|
|
30
|
+
.catch(error => {
|
|
31
|
+
throw error;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const onInteractiveCallback = useCallback(
|
|
35
|
+
(TTI: number, listName: string) => {
|
|
36
|
+
onInteractive(TTI, listName);
|
|
37
|
+
connection?.send('newListTTIData', {
|
|
38
|
+
TTI,
|
|
39
|
+
listName,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
[connection, onInteractive],
|
|
43
|
+
);
|
|
44
|
+
const onBlankAreaCallback = useCallback(
|
|
45
|
+
(offsetStart: number, offsetEnd: number, listName: string) => {
|
|
46
|
+
onBlankArea(offsetStart, offsetEnd, listName);
|
|
47
|
+
const blankArea = Math.max(Math.max(offsetStart, offsetEnd), 0);
|
|
48
|
+
connection?.send('newBlankData', {
|
|
49
|
+
offset: blankArea,
|
|
50
|
+
listName,
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
[connection, onBlankArea],
|
|
54
|
+
);
|
|
55
|
+
return (
|
|
56
|
+
<ListsProfilerContextProvider
|
|
57
|
+
value={{
|
|
58
|
+
onInteractive: onInteractiveCallback,
|
|
59
|
+
onBlankArea: onBlankAreaCallback,
|
|
60
|
+
}}
|
|
61
|
+
>
|
|
62
|
+
{children}
|
|
63
|
+
</ListsProfilerContextProvider>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default ListsProfiler;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ListsProfilerController {
|
|
4
|
+
onInteractive: (TTI: number, listName: string) => void;
|
|
5
|
+
onBlankArea: (offsetStart: number, offsetEnd: number, listName: string) => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const ListsProfilerContext = React.createContext<ListsProfilerController>({
|
|
9
|
+
onInteractive: () => {},
|
|
10
|
+
onBlankArea: () => {},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const ListsProfilerContextProvider = ListsProfilerContext.Provider;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type {KeplerTurboModule} from '@amazon-devices/keplerscript-turbomodule-api';
|
|
2
|
+
import {TurboModuleRegistry} from '@amazon-devices/keplerscript-turbomodule-api';
|
|
3
|
+
|
|
4
|
+
interface Spec extends KeplerTurboModule {
|
|
5
|
+
invokeCallback: () => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const nativeModule = TurboModuleRegistry.get<Spec>('AmazonReactNativePerformanceListsProfilerModule') as Spec;
|
|
9
|
+
|
|
10
|
+
interface ListsProfilerModule {
|
|
11
|
+
invokeCallback: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const module: ListsProfilerModule = {
|
|
15
|
+
invokeCallback() {
|
|
16
|
+
if (!nativeModule) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
'Lists profiler module not found in NativeModules. Chances are you\'re in a test environment, but the mocks have not been setup correctly');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
nativeModule.invokeCallback();
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default module;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface ListsProfilerProps {
|
|
2
|
+
/**
|
|
3
|
+
* Triggered when a list wrapped in a list performance view becomes interactive.
|
|
4
|
+
* @param TTI: Reported time-to-interactive
|
|
5
|
+
* @param listName - Name of the list that triggered the event defined in the list performance view
|
|
6
|
+
*/
|
|
7
|
+
onInteractive?: (TTI: number, listName: string) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Triggered when a list wrapped in a list performance view is scrolled and reports a blank area.
|
|
10
|
+
* @param offsetStart - Offset at the beginning of the list (top when the list is vertical)
|
|
11
|
+
* @param offsetEnd - Offset at the end of the list (bottom when the list is vertical)
|
|
12
|
+
* @param listName - Name of the list that triggered the event defined in the list performance view
|
|
13
|
+
*/
|
|
14
|
+
onBlankArea?: (offsetStart: number, offsetEnd: number, listName: string) => void;
|
|
15
|
+
children: JSX.Element;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default ListsProfilerProps;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react-native';
|
|
3
|
+
import { Text } from 'react-native';
|
|
4
|
+
import FlashListPerformanceView from '../FlashListPerformanceView';
|
|
5
|
+
import { ListsProfilerContextProvider } from '../ListsProfilerContext';
|
|
6
|
+
import 'jest-extended';
|
|
7
|
+
|
|
8
|
+
jest.mock('../FlashListPerformanceViewNativeComponent', () => {
|
|
9
|
+
const RN = require('react-native');
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
FlashListPerformanceViewNativeComponent: ({ onInteractive, onBlankAreaEvent, children }: any) => (
|
|
13
|
+
<RN.View>
|
|
14
|
+
<RN.TouchableOpacity testID="interactive" onPress={onInteractive}>
|
|
15
|
+
<RN.Text>Interactive Event</RN.Text>
|
|
16
|
+
</RN.TouchableOpacity>
|
|
17
|
+
<RN.TouchableOpacity testID="blankArea" onPress={onBlankAreaEvent}>
|
|
18
|
+
<RN.Text>Blank Area Event</RN.Text>
|
|
19
|
+
</RN.TouchableOpacity>
|
|
20
|
+
{children}
|
|
21
|
+
</RN.View>
|
|
22
|
+
),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('FlashListPerformanceView', () => {
|
|
27
|
+
let mockListsProfilerController: any;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
mockListsProfilerController = {
|
|
31
|
+
onInteractive: jest.fn(),
|
|
32
|
+
onBlankArea: jest.fn(),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const wrapper = ({ children }: { children: React.ReactElement }) => (
|
|
37
|
+
<ListsProfilerContextProvider value={mockListsProfilerController}>
|
|
38
|
+
{children}
|
|
39
|
+
</ListsProfilerContextProvider>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
it('calls listsProfilerController.onInteractive on interactive event', () => {
|
|
43
|
+
const { getByTestId } = render(
|
|
44
|
+
<FlashListPerformanceView listName="TestList">
|
|
45
|
+
<Text>Child</Text>
|
|
46
|
+
</FlashListPerformanceView>,
|
|
47
|
+
{ wrapper }
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
fireEvent.press(getByTestId('interactive'), {
|
|
51
|
+
nativeEvent: { timestamp: Date.now() },
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(mockListsProfilerController.onInteractive).toHaveBeenCalledWith(expect.any(Number), 'TestList');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('calls listsProfilerController.onBlankArea on blank area event', () => {
|
|
58
|
+
const { getByTestId } = render(
|
|
59
|
+
<FlashListPerformanceView listName="TestList">
|
|
60
|
+
<Text>Child</Text>
|
|
61
|
+
</FlashListPerformanceView>,
|
|
62
|
+
{ wrapper }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
fireEvent.press(getByTestId('blankArea'), {
|
|
66
|
+
nativeEvent: { offsetStart: 100, offsetEnd: 200 },
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(mockListsProfilerController.onBlankArea).toHaveBeenCalledWith(100, 200, 'TestList');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react-native';
|
|
3
|
+
import { Text } from 'react-native';
|
|
4
|
+
import FlatListPerformanceView from '../FlatListPerformanceView';
|
|
5
|
+
import { ListsProfilerContextProvider } from '../ListsProfilerContext';
|
|
6
|
+
import 'jest-extended';
|
|
7
|
+
|
|
8
|
+
jest.mock('../FlatListPerformanceViewNativeComponent', () => {
|
|
9
|
+
const RN = require('react-native');
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
FlatListPerformanceViewNativeComponent: ({ onInteractive, onBlankAreaEvent, children }: any) => (
|
|
13
|
+
<RN.View>
|
|
14
|
+
<RN.TouchableOpacity testID="interactive" onPress={onInteractive}>
|
|
15
|
+
<RN.Text>Interactive Event</RN.Text>
|
|
16
|
+
</RN.TouchableOpacity>
|
|
17
|
+
<RN.TouchableOpacity testID="blankArea" onPress={onBlankAreaEvent}>
|
|
18
|
+
<RN.Text>Blank Area Event</RN.Text>
|
|
19
|
+
</RN.TouchableOpacity>
|
|
20
|
+
{children}
|
|
21
|
+
</RN.View>
|
|
22
|
+
),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('FlatListPerformanceView', () => {
|
|
27
|
+
let mockOnInteractive: jest.Mock;
|
|
28
|
+
let mockOnBlankArea: jest.Mock;
|
|
29
|
+
let mockListsProfilerController: any;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
mockOnInteractive = jest.fn();
|
|
33
|
+
mockOnBlankArea = jest.fn();
|
|
34
|
+
mockListsProfilerController = {
|
|
35
|
+
onInteractive: jest.fn(),
|
|
36
|
+
onBlankArea: jest.fn(),
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const wrapper = ({ children }: { children: React.ReactElement }) => (
|
|
41
|
+
<ListsProfilerContextProvider value={mockListsProfilerController}>
|
|
42
|
+
{children}
|
|
43
|
+
</ListsProfilerContextProvider>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
it('calls onInteractive and listsProfilerController.onInteractive on interactive event', () => {
|
|
47
|
+
const { getByTestId } = render(
|
|
48
|
+
<FlatListPerformanceView listName="TestList" onInteractive={mockOnInteractive}>
|
|
49
|
+
<Text>Child</Text>
|
|
50
|
+
</FlatListPerformanceView>,
|
|
51
|
+
{ wrapper }
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
fireEvent.press(getByTestId('interactive'), {
|
|
55
|
+
nativeEvent: { timestamp: Date.now() },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(mockOnInteractive).toHaveBeenCalledWith(expect.any(Number), 'TestList');
|
|
59
|
+
expect(mockListsProfilerController.onInteractive).toHaveBeenCalledWith(expect.any(Number), 'TestList');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('calls onBlankArea and listsProfilerController.onBlankArea on blank area event', () => {
|
|
63
|
+
const { getByTestId } = render(
|
|
64
|
+
<FlatListPerformanceView listName="TestList" onBlankArea={mockOnBlankArea}>
|
|
65
|
+
<Text>Child</Text>
|
|
66
|
+
</FlatListPerformanceView>,
|
|
67
|
+
{ wrapper }
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
fireEvent.press(getByTestId('blankArea'), {
|
|
71
|
+
nativeEvent: { offsetStart: 100, offsetEnd: 200 },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(mockOnBlankArea).toHaveBeenCalledWith(100, 200, 'TestList');
|
|
75
|
+
expect(mockListsProfilerController.onBlankArea).toHaveBeenCalledWith(100, 200, 'TestList');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
3
|
+
import ListsProfiler from '../ListsProfiler';
|
|
4
|
+
import { ListsProfilerContext } from '../ListsProfilerContext';
|
|
5
|
+
|
|
6
|
+
jest.mock('react-native-flipper', () => ({
|
|
7
|
+
addPlugin: jest.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
describe('ListsProfiler', () => {
|
|
11
|
+
let mockOnInteractive: jest.Mock;
|
|
12
|
+
let mockOnBlankArea: jest.Mock;
|
|
13
|
+
let mockConnection: { send: jest.Mock };
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
mockOnInteractive = jest.fn();
|
|
17
|
+
mockOnBlankArea = jest.fn();
|
|
18
|
+
mockConnection = {
|
|
19
|
+
send: jest.fn(),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
(require('react-native-flipper').addPlugin as jest.Mock).mockImplementation(({ onConnect }: { onConnect: (connection: any) => void }) => {
|
|
23
|
+
onConnect(mockConnection);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('calls Flipper addPlugin on mount', () => {
|
|
28
|
+
const wrapper = ({children}: {children: React.ReactElement}) => (
|
|
29
|
+
<ListsProfiler onInteractive={mockOnInteractive} onBlankArea={mockOnBlankArea}>{children}</ListsProfiler>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
renderHook(() => React.useContext(ListsProfilerContext), { wrapper });
|
|
33
|
+
|
|
34
|
+
expect(require('react-native-flipper').addPlugin).toHaveBeenCalledTimes(1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('invokes onInteractive callback', () => {
|
|
38
|
+
const wrapper = ({children}: {children: React.ReactElement}) => (
|
|
39
|
+
<ListsProfiler onInteractive={mockOnInteractive} onBlankArea={mockOnBlankArea}>{children}</ListsProfiler>
|
|
40
|
+
);
|
|
41
|
+
const { result } = renderHook(() => React.useContext(ListsProfilerContext), { wrapper });
|
|
42
|
+
|
|
43
|
+
result.current.onInteractive(2000, 'TestList');
|
|
44
|
+
|
|
45
|
+
expect(mockOnInteractive).toHaveBeenCalledWith(2000, 'TestList');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('invokes onBlankArea callback', () => {
|
|
49
|
+
const wrapper = ({children}: {children: React.ReactElement}) => (
|
|
50
|
+
<ListsProfiler onInteractive={mockOnInteractive} onBlankArea={mockOnBlankArea}>{children}</ListsProfiler>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const { result } = renderHook(() => React.useContext(ListsProfilerContext), { wrapper });
|
|
54
|
+
|
|
55
|
+
result.current.onBlankArea(100, 200, 'TestList');
|
|
56
|
+
|
|
57
|
+
expect(mockOnBlankArea).toHaveBeenCalledWith(100, 200, 'TestList');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
package/src/index.ts
ADDED