* Copyright (c) 2024 Huawei Technologies Co., Ltd.
*
* This source code is licensed under the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree.
*/
import { TestCase, TestSuite } from '@rnoh/testerino';
import { Platform, ScrollView, StyleSheet, View } from 'react-native';
import React from 'react';
import { COMMON_PROPS, getScrollViewContent } from './fixtures';
import { useEffect, useRef, useState } from 'react';
import { Button, ObjectDisplayer } from '../../components';
export function MiscPropsTest() {
return (
<TestSuite name="misc props">
<TestCase
modal
itShould="scroll should be disabled (it renders with the 5th element at the top)">
<View style={styles.wrapperView}>
<ScrollView {...COMMON_PROPS} scrollEnabled={false} />
</View>
</TestCase>
<TestCase modal itShould="display horizontal scroll view">
<View
style={{
width: '100%',
height: 150,
}}>
<ScrollView {...COMMON_PROPS} horizontal={true} />
</View>
</TestCase>
<TestCase
modal
itShould="display ScrollView with the third view at the top (contentOffset)"
//https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/305
>
<ContentOffsetTestCase />
</TestCase>
<TestCase
modal
itShould="scroll when contentOffset property is changed (contentOffset)"
//https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/305
>
<ToggleContentOffsetTestCase />
</TestCase>
<TestCase
modal
itShould="toggle backface visibility on button press (the component should become invisible)">
<BackfaceVisibilityTestCase />
</TestCase>
<TestCase
modal
skip={Platform.select({ android: 'fails', harmony: 'fails on Android' })}
itShould="display ScrollView with different contentInsets (contentInset)"
//https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/304
>
<View style={styles.wrapperView}>
<ScrollView
{...COMMON_PROPS}
contentInset={{ top: 10, right: 20, bottom: 30, left: 40 }}
/>
</View>
</TestCase>
<TestCase
modal
itShould="display current contentHeight (onContentSizeChange)">
<OnContentSizeChangeTestCase />
</TestCase>
<TestCase
modal
itShould="display onScroll native event throttled every second">
<ObjectDisplayer
renderContent={setObject => {
return (
<ScrollView
{...COMMON_PROPS}
scrollEventThrottle={1000}
onScroll={(e: { nativeEvent: Object }) => {
setObject(e.nativeEvent);
}}
/>
);
}}
/>
</TestCase>
<TestCase
modal
itShould="the left scrollview should decelerate faster (stops earlier) than the right one (decelarationRate)">
<View style={[styles.wrapperView, { flexDirection: 'row' }]}>
<ScrollView {...COMMON_PROPS} decelerationRate={0.8} />
<ScrollView {...COMMON_PROPS} decelerationRate={0.999} />
</View>
</TestCase>
<TestCase
modal
itShould="the left scrollview should bounce (briefly scroll beyond the content to show the view below and then come back to top/bottom accordingly)">
<View style={[styles.wrapperView, { flexDirection: 'row' }]}>
<ScrollView {...COMMON_PROPS} />
<ScrollView {...COMMON_PROPS} bounces={false} />
</View>
</TestCase>
<TestCase
modal
skip={Platform.select({ android: 'fails', harmony: 'fails on Android' })}
itShould="scroll outside of the content when pressing the button (scrollToOverflowEnabled)"
//https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/315
>
<ScrollToOverflowEnabledTestCase />
</TestCase>
<TestCase
modal
skip
itShould="the left scrollview should allow for nested scroll while the right one shouldn't (nestedScrollEnabled)"
//https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/312
>
<View
style={[
styles.wrapperView,
{ flexDirection: 'row', alignContent: 'space-between' },
]}>
<ScrollView {...COMMON_PROPS}>
<ScrollView
nestedScrollEnabled
style={{
width: '70%',
height: 200,
borderColor: 'firebrick',
borderWidth: 2,
}}>
{getScrollViewContent({
style: { backgroundColor: 'green' },
amountOfChildren: 5,
})}
</ScrollView>
{getScrollViewContent({})}
</ScrollView>
<ScrollView {...COMMON_PROPS}>
<ScrollView
nestedScrollEnabled={false}
style={{
width: '70%',
height: 200,
borderColor: 'firebrick',
borderWidth: 2,
}}>
{getScrollViewContent({
style: { backgroundColor: 'green' },
amountOfChildren: 5,
})}
</ScrollView>
{getScrollViewContent({})}
</ScrollView>
</View>
</TestCase>
<TestCase
modal
itShould="scroll down on the btn press, but prevent scrolling by dragging (scrollEnabled)">
<ScrollEnabledTestCase />
</TestCase>
<TestCase
modal
skip // https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/499
itShould="render scroll view with different fading edge length (fadingEdgeLength)">
<ScrollViewFadingEdgeLengthTest />
</TestCase>
</TestSuite>
);
}
function ScrollEnabledTestCase() {
const scrollRef = React.useRef<ScrollView>(null);
return (
<View style={styles.wrapperView}>
<Button
label={'Scroll To offset y 150'}
onPress={() => {
scrollRef.current?.scrollTo({ x: 0, y: 150, animated: false });
}}
/>
<ScrollView style={{ flex: 1 }} scrollEnabled={false} ref={scrollRef}>
{getScrollViewContent({})}
</ScrollView>
</View>
);
}
function ScrollToOverflowEnabledTestCase() {
const ref = useRef<ScrollView>(null);
return (
<View style={styles.wrapperView}>
<Button
label={'Scroll outside of the content'}
onPress={() => {
ref.current?.scrollTo({ x: 0, y: -60, animated: true });
}}
/>
<ScrollView scrollToOverflowEnabled={true} ref={ref}>
{getScrollViewContent({})}
</ScrollView>
</View>
);
}
function OnContentSizeChangeTestCase() {
const [amountOfChildren, setAmountOfChildren] = useState(3);
return (
<ObjectDisplayer
renderContent={setObject => {
return (
<View style={{ width: '100%', height: '70%' }}>
<Button
label={'Add one more item'}
onPress={() => {
setAmountOfChildren(amountOfChildren + 1);
}}
/>
<ScrollView
onContentSizeChange={(_, contentHeight) => {
setObject({ contentHeight });
}}>
{getScrollViewContent({ amountOfChildren: amountOfChildren })}
</ScrollView>
</View>
);
}}
/>
);
}
function ContentOffsetTestCase() {
return (
<View style={styles.wrapperView}>
<ScrollView
style={{
...styles.wrapperView,
}}
contentOffset={{ x: 0, y: 100 }}>
{getScrollViewContent({})}
</ScrollView>
</View>
);
}
function ToggleContentOffsetTestCase() {
const [contentOffset, setContentOffset] = useState(100);
useEffect(() => {
const id = setInterval(() => {
setContentOffset(prev => (prev + 50) % 200);
}, 1000);
return () => {
clearInterval(id);
};
}, []);
return (
<View style={styles.wrapperView}>
<ScrollView
style={{
...styles.wrapperView,
}}
contentOffset={{ x: 0, y: contentOffset }}>
{getScrollViewContent({})}
</ScrollView>
</View>
);
}
function BackfaceVisibilityTestCase() {
const [backfaceVisibility, setBackfaceVisibility] = useState(true);
return (
<View style={styles.wrapperView}>
<Button
label={`Make backface ${backfaceVisibility ? 'invisible' : 'visible'}`}
onPress={() => {
setBackfaceVisibility(!backfaceVisibility);
}}
/>
<ScrollView
style={{
...styles.wrapperView,
backfaceVisibility: backfaceVisibility ? 'visible' : 'hidden',
transform: [{ rotateX: '180deg' }],
}}>
{getScrollViewContent({})}
</ScrollView>
</View>
);
}
function ScrollViewFadingEdgeLengthTest() {
return (
<View
style={{
width: '100%',
justifyContent: 'center',
backgroundColor: 'blue',
}}>
<View
style={{
height: 400,
marginTop: 50,
marginBottom: 50,
}}>
<ScrollView fadingEdgeLength={100}>
{getScrollViewContent({})}
</ScrollView>
</View>
</View>
);
}
const styles = StyleSheet.create({
wrapperView: {
height: 300,
width: '60%',
},
});