* 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 {
FlatList,
Platform,
RefreshControl,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import { TestCase, TestSuite } from '@rnoh/testerino';
import { useEffect, useState } from 'react';
export const RefreshControlTest = () => {
const [refreshKey, setRefreshKey] = useState(0);
useEffect(() => {
setInterval(() => setRefreshKey(prev => prev + 1), 1000);
}, []);
return (
<TestSuite name="RefreshControl">
<TestCase itShould="display refresh control every second">
<ScrollView
style={{ height: 128, backgroundColor: 'white' }}
refreshControl={
<RefreshControl
refreshing={refreshKey % 2 === 0}
onRefresh={() => { }}
/>
}
/>
</TestCase>
<TestCase itShould="display refresh control with tintColor">
<ScrollView
style={{ height: 128, backgroundColor: 'white' }}
refreshControl={
<RefreshControl
refreshing={refreshKey % 2 === 0}
tintColor={'#FFC0CB'}
onRefresh={() => { }}
/>
}
/>
</TestCase>
<TestCase
modal
itShould="be refreshing for one second after pull to refresh">
<PullToRefreshExample />
</TestCase>
<TestCase
modal
itShould="immediately stop refreshing after pulling to refresh">
<PullToRefreshExample doNothingOnRefresh />
</TestCase>
<TestCase
modal
itShould="refresh with progressViewOffset = undefined"
skip // there is a restriction on how tall the progress view can be - should be removed in API 11 https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/624
>
<PullToRefreshProgressViewOffset />
</TestCase>
<TestCase
modal
itShould="refresh with progressViewOffset = 50"
skip // there is a restriction on how tall the progress view can be - should be removed in API 11 https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/624
>
<PullToRefreshProgressViewOffset progressViewOffset={50} />
</TestCase>
<TestCase
modal
itShould="refresh with progressViewOffset = 100"
skip // there is a restriction on how tall the progress view can be - should be removed in API 11 https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/624
>
<PullToRefreshProgressViewOffset progressViewOffset={100} />
</TestCase>
<TestCase
itShould="display double refresh control for 2 seconds in nested scroll view"
modal
skip={Platform.select({ harmony: true, android: false })} // https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/770
>
<PullToRefreshInNestedScrollViews />
</TestCase>
<TestCase
itShould="display one refresh control - for 3 seconds in nested scroll view"
modal>
<PullToRefreshInNestedScrollViewsDifferentSource />
</TestCase>
</TestSuite>
);
};
function PullToRefreshExample({
doNothingOnRefresh,
}: {
doNothingOnRefresh?: boolean;
}) {
const [isRefreshing, setIsRefreshing] = useState(false);
return (
<FlatList
style={{ height: 256 }}
refreshing={isRefreshing}
onRefresh={() => {
if (!doNothingOnRefresh) {
setIsRefreshing(true);
setTimeout(() => setIsRefreshing(false), 1000);
}
}}
data={[1, 2, 3, 4, 5]}
renderItem={({ item }) => (
<Text style={{ height: 96, borderBottomWidth: 1 }}>{item}</Text>
)}
/>
);
}
function PullToRefreshProgressViewOffset({
progressViewOffset,
}: {
progressViewOffset?: number;
}) {
const [refreshing, setIsRefreshing] = useState(false);
return (
<ScrollView
style={{ height: '90%', backgroundColor: 'lightgray' }}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={() => {
setIsRefreshing(true);
setTimeout(() => setIsRefreshing(false), 3000);
}}
progressViewOffset={progressViewOffset}
/>
}>
<View style={{ height: 50, backgroundColor: 'lightblue' }}>
<Text>First Content Component</Text>
</View>
<View style={{ height: 50, backgroundColor: 'lightgreen' }}>
<Text>Second Content Component</Text>
</View>
<View style={{ height: 50, backgroundColor: 'lightblue' }}>
<Text>Third Content Component</Text>
</View>
</ScrollView>
);
}
const wait = (timeout: number) => {
return new Promise(resolve => {
setTimeout(resolve, timeout);
});
};
const PullToRefreshInNestedScrollViews = () => {
const [refreshing, setRefrehing] = useState(false);
const onRefresh = () => {
setRefrehing(true);
wait(2000).then(() => {
setRefrehing(false);
});
};
return (
<ScrollView
contentContainerStyle={styles.scrollView}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<ScrollView
contentContainerStyle={{
...styles.scrollView,
backgroundColor: 'white',
}}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
</ScrollView>
</ScrollView>
);
};
const PullToRefreshInNestedScrollViewsDifferentSource = () => {
const [firstRefreshing, setFirstRefrehing] = useState(false);
const [secondRefreshing, setSecondRefrehing] = useState(false);
const onFirstsRefresh = () => {
setFirstRefrehing(true);
wait(3000).then(() => {
setFirstRefrehing(false);
});
};
const onSecondRefresh = () => {
setSecondRefrehing(true);
wait(4000).then(() => {
setSecondRefrehing(false);
});
};
return (
<ScrollView
contentContainerStyle={styles.scrollView}
refreshControl={
<RefreshControl
refreshing={firstRefreshing}
onRefresh={onFirstsRefresh}
/>
}>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<Text>outer-scrollView</Text>
<ScrollView
contentContainerStyle={{
...styles.scrollView,
backgroundColor: 'white',
}}
refreshControl={
<RefreshControl
refreshing={secondRefreshing}
onRefresh={onSecondRefresh}
/>
}>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView 按住该区域下拉刷新,刷新标识不回弹回
</Text>
<Text style={styles.text}>
inner-scrollView Press and hold down the area to refresh. The refresh
label does not bounce back
</Text>
</ScrollView>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollView: {
flex: 1,
backgroundColor: 'pink',
alignItems: 'center',
justifyContent: 'center',
},
text: {
backgroundColor: 'green',
},
});