Files
react-native/packages/rn-tester/NativeComponentExample/js/MyNativeView.js
T
Riccardo Cipolleschi 7de3111f9b Add Maestro test for New Arch Example (#46541)
Summary:
This change adds automated tests for the New Architecture Examples page in RNTester.
It also updates the NativeComponentExample to make sure that iOS and Android behaves in the same way and in a reliable way.

## Changelog:
[Internal] - Adds

Pull Request resolved: https://github.com/facebook/react-native/pull/46541

Test Plan:
* Android:

https://github.com/user-attachments/assets/65ead328-9c4f-4e0f-8b9b-992ffb584566

* iOS:

https://github.com/user-attachments/assets/412a4f68-c9c9-4ff2-a3e9-ae7194deef77

Reviewed By: cortinico

Differential Revision: D62879289

Pulled By: cipolleschi

fbshipit-source-id: 59e15f48f5995b18fd8b3ee24aca726b93e04d9f
2024-09-18 06:15:58 -07:00

274 lines
8.3 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {MyLegacyViewType} from './MyLegacyViewNativeComponent';
import type {MyNativeViewType} from './MyNativeViewNativeComponent';
import RNTMyLegacyNativeView from './MyLegacyViewNativeComponent';
import {
callNativeMethodToAddOverlays,
callNativeMethodToChangeBackgroundColor,
callNativeMethodToRemoveOverlays,
} from './MyLegacyViewNativeComponent';
import RNTMyNativeView, {
Commands as RNTMyNativeViewCommands,
} from './MyNativeViewNativeComponent';
import * as React from 'react';
import {useRef, useState} from 'react';
import {Button, Platform, Text, UIManager, View} from 'react-native';
const colors = [
'#0000FF',
'#FF0000',
'#00FF00',
'#003300',
'#330000',
'#000033',
];
const cornerRadiuses = [0, 20, 40, 60, 80, 100, 120];
class HSBA {
hue: number;
saturation: number;
brightness: number;
alpha: number;
constructor(
hue: number = 0.0,
saturation: number = 0.0,
brightness: number = 0.0,
alpha: number = 0.0,
) {
this.hue = hue;
this.saturation = saturation;
this.brightness = brightness;
this.alpha = alpha;
}
toString(): string {
return `h: ${this.hue}, s: ${this.saturation}, b: ${this.brightness}, a: ${this.alpha}`;
}
}
function beautify(number: number): string {
if (number % 1 === 0) {
return number.toFixed();
}
return number.toFixed(2);
}
type MeasureStruct = {
x: number,
y: number,
width: number,
height: number,
};
const MeasureStructZero: MeasureStruct = {
x: 0,
y: 0,
width: 0,
height: 0,
};
function getTextFor(measureStruct: MeasureStruct): string {
return `x: ${beautify(measureStruct.x)}, y: ${beautify(
measureStruct.y,
)}, width: ${beautify(measureStruct.width)}, height: ${beautify(
measureStruct.height,
)}`;
}
// This is an example component that migrates to use the new architecture.
export default function MyNativeView(props: {}): React.Node {
const containerRef = useRef<React.ElementRef<typeof View> | null>(null);
const ref = useRef<React.ElementRef<MyNativeViewType> | null>(null);
const legacyRef = useRef<React.ElementRef<MyLegacyViewType> | null>(null);
const [currentBGColor, setCurrentBGColor] = useState<number>(0);
const [opacity, setOpacity] = useState(1.0);
const [arrayValues, setArrayValues] = useState([1, 2, 3]);
const [hsba, setHsba] = useState<HSBA>(new HSBA());
const [cornerRadiusIndex, setCornerRadiusIndex] = useState<number>(0);
const [legacyMeasure, setLegacyMeasure] =
useState<MeasureStruct>(MeasureStructZero);
const [legacyMeasureInWindow, setLegacyMeasureInWindow] =
useState<MeasureStruct>(MeasureStructZero);
const [legacyMeasureLayout, setLegacyMeasureLayout] =
useState<MeasureStruct>(MeasureStructZero);
return (
<View ref={containerRef} style={{flex: 1}}>
<Text style={{color: 'red'}}>Fabric View</Text>
<RNTMyNativeView
ref={ref}
style={{flex: 1}}
opacity={opacity}
values={arrayValues}
onIntArrayChanged={event => {
console.log(event.nativeEvent.values);
console.log(event.nativeEvent.boolValues);
console.log(event.nativeEvent.floats);
console.log(event.nativeEvent.doubles);
console.log(event.nativeEvent.yesNos);
console.log(event.nativeEvent.strings);
console.log(event.nativeEvent.latLons);
console.log(event.nativeEvent.multiArrays);
}}
onLegacyStyleEvent={event => {
console.log(event.nativeEvent.string);
}}
/>
<Text style={{color: 'red'}}>Legacy View</Text>
<RNTMyLegacyNativeView
ref={legacyRef}
style={{flex: 1}}
opacity={opacity}
onColorChanged={event => {
const normalizedHue =
Platform.OS === 'android'
? event.nativeEvent.backgroundColor.hue
: event.nativeEvent.backgroundColor.hue * 360;
const normalizedAlpha =
Platform.OS === 'android'
? event.nativeEvent.backgroundColor.alpha
: event.nativeEvent.backgroundColor.alpha * 255;
setHsba(
new HSBA(
normalizedHue,
event.nativeEvent.backgroundColor.saturation,
event.nativeEvent.backgroundColor.brightness,
normalizedAlpha,
),
);
}}
/>
<Text style={{color: 'green', textAlign: 'center'}}>
HSBA: {hsba.toString()}
</Text>
<Text style={{color: 'green', textAlign: 'center'}}>
Constants From Interop Layer:{' '}
{UIManager.getViewManagerConfig('RNTMyLegacyNativeView').Constants.PI}
</Text>
<Button
title="Change Background"
onPress={() => {
let nextBGColor =
currentBGColor + 1 >= colors.length ? 0 : currentBGColor + 1;
let newColor = colors[nextBGColor];
RNTMyNativeViewCommands.callNativeMethodToChangeBackgroundColor(
// $FlowFixMe[incompatible-call]
ref.current,
newColor,
);
callNativeMethodToChangeBackgroundColor(legacyRef.current, newColor);
setCurrentBGColor(nextBGColor);
}}
/>
<Button
title="Add Overlays"
onPress={() => {
let randomColorId = Math.floor(Math.random() * 5);
let overlayColors = [
colors[randomColorId],
colors[(randomColorId + 1) % 5],
];
RNTMyNativeViewCommands.callNativeMethodToAddOverlays(
// $FlowFixMe[incompatible-call]
ref.current,
overlayColors,
);
callNativeMethodToAddOverlays(legacyRef.current, overlayColors);
}}
/>
<Button
title="Remove Overlays"
onPress={() => {
RNTMyNativeViewCommands.callNativeMethodToRemoveOverlays(
// $FlowFixMe[incompatible-call]
ref.current,
);
callNativeMethodToRemoveOverlays(legacyRef.current);
}}
/>
<Button
title="Set Opacity"
onPress={() => {
setOpacity(Math.random());
setArrayValues([
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100),
]);
}}
/>
<Button
title="Console.log Measure"
onPress={() => {
ref.current?.measure((x, y, width, height) => {
console.log(x, y, width, height);
});
legacyRef.current?.measure((x, y, width, height) => {
setLegacyMeasure({x, y, width, height});
});
legacyRef.current?.measureInWindow((x, y, width, height) => {
setLegacyMeasureInWindow({x, y, width, height});
});
if (containerRef.current) {
legacyRef.current?.measureLayout(
// $FlowFixMe[incompatible-call]
containerRef.current,
(x, y, width, height) => {
setLegacyMeasureLayout({x, y, width, height});
},
);
}
}}
/>
<Button
title="Fire Legacy Style Event"
onPress={() => {
RNTMyNativeViewCommands.fireLagacyStyleEvent(
// $FlowFixMe[incompatible-call]
ref.current,
);
}}
/>
<Text style={{color: 'green', textAlign: 'center'}}>
&gt; Interop Layer Measurements &lt;
</Text>
<Text style={{color: 'green', textAlign: 'center'}}>
measure {getTextFor(legacyMeasure)}
</Text>
<Text style={{color: 'green', textAlign: 'center'}}>
InWindow {getTextFor(legacyMeasureInWindow)}
</Text>
<Text style={{color: 'green', textAlign: 'center'}}>
InLayout {getTextFor(legacyMeasureLayout)}
</Text>
<Button
title="Test setNativeProps"
onPress={() => {
const newCRIndex =
cornerRadiusIndex + 1 >= cornerRadiuses.length
? 0
: cornerRadiusIndex + 1;
setCornerRadiusIndex(newCRIndex);
legacyRef.current?.setNativeProps({
cornerRadius: cornerRadiuses[newCRIndex],
});
}}
/>
</View>
);
}