Skip to content

Commit e9c8fee

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Add Example for InteropLayer on RNTester (#51260)
Summary: Pull Request resolved: #51260 This is a preparatory change that adds an example to RNTester for the Fabric interop layer on iOS. This example is needed to create a Jest E2E tests that will make sure that the Fabric Interop Layer can properly add views as subviews. We discovered the bug thanks to react-native-maps. ## Changelog: [Internal] - Add Example for the Fabric Interop Layer to RNTester iOS Reviewed By: cortinico Differential Revision: D74579737 fbshipit-source-id: 0c1bbb06790b01313cd98aa4b7152d8aba0cded3
1 parent 337ae3b commit e9c8fee

File tree

6 files changed

+221
-0
lines changed

6 files changed

+221
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <UIKit/UIKit.h>
9+
10+
NS_ASSUME_NONNULL_BEGIN
11+
12+
@interface InteropTestView : UIView
13+
@end
14+
15+
NS_ASSUME_NONNULL_END
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "RCTInteropTestView.h"
9+
10+
@implementation InteropTestView
11+
12+
- (instancetype)initWithFrame:(CGRect)frame
13+
{
14+
self = [super initWithFrame:frame];
15+
return self;
16+
}
17+
18+
@end
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <React/RCTViewManager.h>
9+
10+
NS_ASSUME_NONNULL_BEGIN
11+
12+
@interface InteropTestViewManager : RCTViewManager
13+
@end
14+
NS_ASSUME_NONNULL_END
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "RCTInteropTestViewManager.h"
9+
#import "RCTInteropTestView.h"
10+
11+
@implementation InteropTestViewManager
12+
13+
RCT_EXPORT_MODULE(InteropTestView)
14+
15+
- (UIView *)view
16+
{
17+
return [[InteropTestView alloc] init];
18+
}
19+
20+
@end
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
* @flow
9+
*/
10+
11+
'use strict';
12+
import type {ViewProps} from 'react-native';
13+
14+
import React, {useState} from 'react';
15+
import {
16+
Button,
17+
StyleSheet,
18+
Text,
19+
View,
20+
requireNativeComponent,
21+
useColorScheme,
22+
} from 'react-native';
23+
24+
type SectionProps = {
25+
title: string,
26+
children?: React.Node,
27+
};
28+
29+
const WHITE = '#ffffff';
30+
const BLACK = '#000000';
31+
32+
// ========== JS Definition of the Native RCTInteropTestView component ========
33+
type InteropTestViewProps = {
34+
// Add custom props here if needed
35+
...ViewProps,
36+
};
37+
38+
const NativeInteropTestView =
39+
requireNativeComponent<InteropTestViewProps>('InteropTestView');
40+
41+
const InteropTestView = (props: InteropTestViewProps) => {
42+
return <NativeInteropTestView {...props} />;
43+
};
44+
45+
// =============================================================================
46+
47+
function Section({children, title}: SectionProps): React.Node {
48+
const isDarkMode = useColorScheme() === 'dark';
49+
return (
50+
<View style={styles.sectionContainer}>
51+
<Text
52+
style={[
53+
styles.sectionTitle,
54+
{
55+
color: isDarkMode ? WHITE : BLACK,
56+
},
57+
]}>
58+
{title}
59+
</Text>
60+
<Text
61+
style={[
62+
styles.sectionDescription,
63+
{
64+
color: isDarkMode ? WHITE : BLACK,
65+
},
66+
]}>
67+
{children}
68+
</Text>
69+
</View>
70+
);
71+
}
72+
73+
function AddChildrenForInteropLayer() {
74+
const isDarkMode = useColorScheme() === 'dark';
75+
const [squares, setSquares] = useState<Array<number>>([0, 1, 2, 3, 4]);
76+
const addMarker = () => {
77+
setSquares(p => [...p, p.length + 1]);
78+
};
79+
return (
80+
<View
81+
style={{
82+
backgroundColor: isDarkMode ? BLACK : WHITE,
83+
}}>
84+
<Section title="Squares">
85+
<Button title="Add Marker" onPress={addMarker} />
86+
<Text>{`Number of squares: ${squares.length}`}</Text>
87+
</Section>
88+
<Section title="Custom native view">
89+
<InteropTestView style={styles.customView}>
90+
{squares.map((_, index) => (
91+
<View key={index} style={styles.customViewChild} />
92+
))}
93+
</InteropTestView>
94+
</Section>
95+
<Section title="Regular view">
96+
<View style={styles.customView}>
97+
{squares.map((_, index) => (
98+
<View key={index} style={styles.customViewChild} />
99+
))}
100+
</View>
101+
</Section>
102+
</View>
103+
);
104+
}
105+
106+
const styles = StyleSheet.create({
107+
sectionContainer: {
108+
marginTop: 32,
109+
paddingHorizontal: 24,
110+
},
111+
sectionTitle: {
112+
fontSize: 24,
113+
fontWeight: '600',
114+
},
115+
sectionDescription: {
116+
marginTop: 8,
117+
fontSize: 18,
118+
fontWeight: '400',
119+
},
120+
highlight: {
121+
fontWeight: '700',
122+
},
123+
customView: {
124+
width: 300,
125+
height: 200,
126+
backgroundColor: 'yellow',
127+
flexWrap: 'wrap',
128+
gap: 10,
129+
},
130+
customViewChild: {
131+
width: 50,
132+
height: 50,
133+
backgroundColor: 'blue',
134+
},
135+
});
136+
137+
exports.title = 'Fabric Interop Layer';
138+
exports.category = 'UI';
139+
exports.description = 'A set test cases for the Fabric Interop Layer.';
140+
exports.examples = [
141+
{
142+
title: 'Add children to Interop Layer',
143+
description: 'Add children to Interop Layer',
144+
name: 'Add Children to interop layer',
145+
render(): React.Node {
146+
return <AddChildrenForInteropLayer />;
147+
},
148+
},
149+
];

packages/rn-tester/js/utils/RNTesterList.ios.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ const Components: Array<RNTesterModuleInfo> = [
146146
category: 'UI',
147147
module: require('../examples/NewArchitecture/NewArchitectureExample'),
148148
},
149+
{
150+
key: 'FabricInteropLayer',
151+
category: 'UI',
152+
module: require('../examples/FabricInteropLayer/FabricInteropLayer'),
153+
},
149154
{
150155
key: 'PerformanceComparisonExample',
151156
category: 'Basic',

0 commit comments

Comments
 (0)