Skip to content

Commit ec0ea94

Browse files
LKuchnokligarski
andauthored
chore(test): new screen and scenario for specialEffects: scrollToTop prop (#3934)
## Description Adds a test scenario for the specialEffects.repeatedTabSelection.**scrollToTop** property on tab routes. The scenario uses three tabs with a scrollable list each, covering all meaningful states of the property: explicitly enabled, explicitly disabled, and absent (default platform behavior). The scenario also validates that scrollToTop only triggers on a repeated tap of the already-active tab - switching away and back must preserve scroll position. Closes: software-mansion/react-native-screens-labs#1154 ## Changes **test-tabs-special-effects/index.tsx** New test screen component with three tabs sharing a single ScrollScreen component. **test-tabs-special-effects/scenario.md** Manual test scenario with four sections: scrollToTop: true, scrollToTop: false, no specialEffects (default), and a switching-away-and-back case that verifies scroll position is preserved on non-repeated tab navigation. **single-feature-tests/tabs/index.ts** Registered TestTabsSpecialEffects in the tabs scenario group so the screen is reachable from the test navigator. ## Test demo https://github.com/user-attachments/assets/0047ac91-0fd3-4e86-8923-5951616a6399 --------- Co-authored-by: Krzysztof Ligarski <63918941+kligarski@users.noreply.github.com>
1 parent ddda1e0 commit ec0ea94

3 files changed

Lines changed: 193 additions & 0 deletions

File tree

apps/src/tests/single-feature-tests/tabs/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import TestTabsPreventNativeSelection from './test-tabs-prevent-native-selection
1414
import TestTabsStaleStateUpdateRejection from './test-tabs-stale-update-rejection';
1515
import TestTabsTabBarMinimizeBehavior from './test-tabs-tab-bar-minimize-behavior-ios';
1616
import TestTabsTabBarControllerMode from './test-tabs-tab-bar-controller-mode-ios';
17+
import TestTabsSpecialEffectsScrollToTop from './test-tabs-special-effects-scroll-to-top';
1718

1819
const scenarios = {
1920
BottomAccessoryScenario,
@@ -30,6 +31,7 @@ const scenarios = {
3031
TestTabsStaleStateUpdateRejection,
3132
TestTabsTabBarMinimizeBehavior,
3233
TestTabsTabBarControllerMode,
34+
TestTabsSpecialEffectsScrollToTop,
3335
};
3436

3537
const TabsScenarioGroup: ScenarioGroup<keyof typeof scenarios> = {
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React from 'react';
2+
import { ScrollView, StyleSheet, Text } from 'react-native';
3+
import type { ScenarioDescription } from '@apps/tests/shared/helpers';
4+
import { createScenario } from '@apps/tests/shared/helpers';
5+
import {
6+
TabsContainer,
7+
type TabRouteConfig,
8+
DEFAULT_TAB_ROUTE_OPTIONS,
9+
} from '@apps/shared/gamma/containers/tabs';
10+
11+
const scenarioDescription: ScenarioDescription = {
12+
name: 'Tabs scrollToTop special effect',
13+
key: 'test-tabs-special-effects-scroll-to-top',
14+
details:
15+
'Test settings of scrollToTop specialEffect.',
16+
platforms: ['ios', 'android'],
17+
};
18+
19+
export function ScrollScreen() {
20+
return (
21+
<ScrollView>
22+
<Text style={styles.hint}>Scroll Screen — scroll down or re-tap the tab.</Text>
23+
{Array.from({ length: 50 }, (_, i) => (
24+
<Text key={i} style={styles.item}>
25+
Item {i + 1}
26+
</Text>
27+
))}
28+
</ScrollView>
29+
);
30+
}
31+
32+
const TAB_CONFIGS: TabRouteConfig[] = [
33+
{
34+
name: 'Tab1',
35+
Component: ScrollScreen,
36+
options: {
37+
...DEFAULT_TAB_ROUTE_OPTIONS,
38+
title: 'Tab1',
39+
specialEffects: {
40+
repeatedTabSelection: {
41+
scrollToTop: true,
42+
},
43+
},
44+
},
45+
},
46+
{
47+
name: 'Tab2',
48+
Component: ScrollScreen,
49+
options: {
50+
...DEFAULT_TAB_ROUTE_OPTIONS,
51+
title: 'Tab2',
52+
specialEffects: {
53+
repeatedTabSelection: {
54+
scrollToTop: false
55+
},
56+
},
57+
},
58+
},
59+
{
60+
name: 'Tab3',
61+
Component: ScrollScreen,
62+
options: {
63+
...DEFAULT_TAB_ROUTE_OPTIONS,
64+
title: 'Tab3',
65+
},
66+
},
67+
];
68+
69+
export function App() {
70+
return <TabsContainer routeConfigs={TAB_CONFIGS} />;
71+
}
72+
73+
export default createScenario(App, scenarioDescription);
74+
75+
const styles = StyleSheet.create({
76+
config: {
77+
padding: 40,
78+
},
79+
centered: {
80+
flex: 1,
81+
alignItems: 'center',
82+
justifyContent: 'center',
83+
gap: 16,
84+
},
85+
subtitle: {
86+
textAlign: 'center',
87+
color: '#666',
88+
},
89+
switch: {
90+
marginTop: 20,
91+
marginBottom: 15,
92+
},
93+
hint: {
94+
padding: 16,
95+
color: '#666',
96+
},
97+
item: {
98+
padding: 12,
99+
borderBottomWidth: 1,
100+
borderColor: '#eee',
101+
},
102+
});
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Test Scenario: specialEffects - scrollToTop
2+
3+
## Details
4+
5+
**Description:** This test scenario validates the `specialEffects.repeatedTabSelection.scrollToTop`
6+
property on tab routes. It verifies that re-tapping an already-active
7+
tab scrolls a scrollable screen back to the top when the property is enabled, and
8+
that there is no scroll-to-top behavior when it is disabled or absent.
9+
10+
**OS test creation version:** iOS: 18.4 and 26.2, Android: 16.0 (Baklava).
11+
12+
## E2E test
13+
14+
Other: ongoing research.
15+
16+
## Prerequisites
17+
18+
- iOS device or simulator
19+
- Android emulator
20+
21+
## Note (Optional)
22+
23+
Tab1 has `scrollToTop: true`, Tab2 has `scrollToTop: false`, and Tab3 has no
24+
`specialEffects` configured (default behavior). All three tabs display a scrollable
25+
list of 50 items.
26+
27+
## Steps
28+
29+
### scrollToTop: true
30+
31+
1. Launch the app and navigate to the screen **Tabs specialEffects**.
32+
33+
- [ ] Expected: Three tabs (Tab1, Tab2, Tab3) are visible in the tab bar.
34+
Tab1 is active and displays a scrollable list of items.
35+
36+
2. Scroll down several items in Tab1.
37+
38+
- [ ] Expected: The list scrolls down; items above the fold are no longer visible.
39+
40+
3. Re-tap Tab1 (the already-active tab).
41+
42+
- [ ] Expected: The list animates back to the top of the scroll position
43+
(item 1 is visible).
44+
45+
### scrollToTop: false
46+
47+
4. Tap Tab2.
48+
49+
- [ ] Expected: Tab2 becomes active and displays a scrollable list of items.
50+
51+
5. Scroll down several items in Tab2.
52+
53+
- [ ] Expected: The list scrolls down; items above the fold are no longer visible.
54+
55+
6. Re-tap Tab2 (the already-active tab).
56+
57+
- [ ] Expected: The list does **not** scroll back to the top; scroll position is
58+
preserved.
59+
60+
### no specialEffects (default)
61+
62+
7. Tap Tab3.
63+
64+
- [ ] Expected: Tab3 becomes active and displays a scrollable list of items.
65+
66+
8. Scroll down several items in Tab3.
67+
68+
- [ ] Expected: The list scrolls down; items above the fold are no longer visible.
69+
70+
9. Re-tap Tab3 (the already-active tab).
71+
72+
- [ ] Expected: Observe and note the default behavior - back to the top of the
73+
scroll position (item 1 is visible).
74+
75+
### scrollToTop: true — switching away and back (not a repeated tap)
76+
77+
10. Tap Tab1 and scroll down several items.
78+
79+
- [ ] Expected: Tab1 becomes active. The list scrolls down;
80+
items above the fold are no longer visible.
81+
82+
11. Tap Tab3 to switch away from Tab1.
83+
84+
- [ ] Expected: Tab3 becomes active and displays its scrollable list.
85+
86+
12. Tap Tab1 again.
87+
88+
- [ ] Expected: Tab1 becomes active and the scroll position is **preserved** -
89+
the list does not scroll back to the top.

0 commit comments

Comments
 (0)