From e48622e30b04b6a41cad8a5167aa5aa5cc5ad608 Mon Sep 17 00:00:00 2001 From: lkuchno Date: Tue, 12 May 2026 11:29:45 +0200 Subject: [PATCH 1/5] fix for e2e test scroll to top --- ...est-tabs-special-effects-scroll-to-top.e2e.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts b/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts index ce268e7e00..de548d8cf2 100644 --- a/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts +++ b/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts @@ -5,7 +5,7 @@ import { } from '../../e2e-utils'; /** - * Selects a tab bar item. On iOS, this uses a forced coordinate tap to + * Selects a tab bar item. On iOS, this uses a forced coordinate tap to * ensure the tab is selected even if it is obstructed by the iOS 26 Liquid Glass lens. */ async function forceSelectTabByLabel(label: string) { @@ -16,6 +16,12 @@ async function forceSelectTabByLabel(label: string) { } } +async function scrollDown(targetId: string, scrollViewId: string) { + await waitFor(element(by.id(targetId))) + .toBeVisible() + .whileElement(by.id(scrollViewId)) + .scroll(500, 'down', NaN, 0.85); +} describe('Tabs specialEffects — scrollToTop', () => { beforeAll(async () => { await device.reloadReactNative(); @@ -38,7 +44,7 @@ describe('Tabs specialEffects — scrollToTop', () => { }); it('Tab1 (scrollToTop: true) — re-tapping active tab scrolls list back to top', async () => { - await element(by.id('tab1-scrollview')).scroll(300, 'down', NaN, 0.85); + await scrollDown('tab1-item-22', 'tab1-scrollview'); await expect(element(by.id('tab1-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab1-tab-item-label'); @@ -52,7 +58,7 @@ describe('Tabs specialEffects — scrollToTop', () => { await element(by.id('tab2-tab-item')).tap(); await expect(element(by.id('tab2-item-1'))).toBeVisible(); - await element(by.id('tab2-scrollview')).scroll(300, 'down', NaN, 0.85); + await scrollDown('tab2-item-22', 'tab2-scrollview'); await expect(element(by.id('tab2-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab2-tab-item-label'); @@ -64,7 +70,7 @@ describe('Tabs specialEffects — scrollToTop', () => { await element(by.id('tab3-tab-item')).tap(); await expect(element(by.id('tab3-item-1'))).toBeVisible(); - await element(by.id('tab3-scrollview')).scroll(300, 'down', NaN, 0.85); + await scrollDown('tab3-item-22', 'tab3-scrollview'); await expect(element(by.id('tab3-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab3-tab-item-label'); @@ -78,7 +84,7 @@ describe('Tabs specialEffects — scrollToTop', () => { await forceSelectTabByLabel('tab1-tab-item-label'); await expect(element(by.id('tab1-item-1'))).toBeVisible(); - await element(by.id('tab1-scrollview')).scroll(300, 'down', NaN, 0.85); + await scrollDown('tab1-item-22', 'tab1-scrollview'); await expect(element(by.id('tab1-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab3-tab-item-label'); From 5868f1be9c40d00446d935b3e640a0c18045cf45 Mon Sep 17 00:00:00 2001 From: lkuchno Date: Wed, 13 May 2026 08:50:15 +0200 Subject: [PATCH 2/5] Safe Area View added to screen --- .../index.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx b/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx index 99b01e4cd1..bec113fe10 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ScrollView, StyleSheet, Text } from 'react-native'; +import { Platform, ScrollView, StyleSheet, Text } from 'react-native'; import type { ScenarioDescription } from '@apps/tests/shared/helpers'; import { createScenario } from '@apps/tests/shared/helpers'; import { @@ -7,6 +7,7 @@ import { type TabRouteConfig, DEFAULT_TAB_ROUTE_OPTIONS, } from '@apps/shared/gamma/containers/tabs'; +import { SafeAreaView } from 'react-native-screens/experimental'; const scenarioDescription: ScenarioDescription = { name: 'Tabs special effect scroll to top', @@ -22,14 +23,16 @@ interface ScrollScreenProps { export function ScrollScreen({ tabName }: ScrollScreenProps) { return ( - - Scroll Screen — scroll down or re-tap the tab. - {Array.from({ length: 50 }, (_, i) => ( - - Item {i + 1} - - ))} - + + + Scroll Screen — scroll down or re-tap the tab. + {Array.from({ length: 50 }, (_, i) => ( + + Item {i + 1} + + ))} + + ); } From 4433fa6f1e96bbf0a58012c4e4c0bc923b6e326f Mon Sep 17 00:00:00 2001 From: lkuchno Date: Wed, 13 May 2026 09:41:13 +0200 Subject: [PATCH 3/5] edge define for andrid sav --- .../tabs/test-tabs-special-effects-scroll-to-top/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx b/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx index bec113fe10..627a191ee1 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx @@ -23,7 +23,7 @@ interface ScrollScreenProps { export function ScrollScreen({ tabName }: ScrollScreenProps) { return ( - + Scroll Screen — scroll down or re-tap the tab. {Array.from({ length: 50 }, (_, i) => ( From 9d9e8545efa0e1bd453fb1a4f648ee8d2d91933e Mon Sep 17 00:00:00 2001 From: lkuchno <45803783+LKuchno@users.noreply.github.com> Date: Wed, 13 May 2026 10:33:08 +0200 Subject: [PATCH 4/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../tabs/test-tabs-special-effects-scroll-to-top/index.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx b/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx index 627a191ee1..11cf651d35 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top/index.tsx @@ -23,7 +23,12 @@ interface ScrollScreenProps { export function ScrollScreen({ tabName }: ScrollScreenProps) { return ( - + Scroll Screen — scroll down or re-tap the tab. {Array.from({ length: 50 }, (_, i) => ( From 6afebf86b4be3f301693c93b15f95850045fd656 Mon Sep 17 00:00:00 2001 From: lkuchno Date: Wed, 13 May 2026 10:46:28 +0200 Subject: [PATCH 5/5] export scrollUntilVisible function and reuse it in e2e test --- FabricExample/e2e/e2e-utils.ts | 10 +++++----- ...est-tabs-special-effects-scroll-to-top.e2e.ts | 16 +++++----------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/FabricExample/e2e/e2e-utils.ts b/FabricExample/e2e/e2e-utils.ts index 65d38c04e9..72c7b931ab 100644 --- a/FabricExample/e2e/e2e-utils.ts +++ b/FabricExample/e2e/e2e-utils.ts @@ -7,7 +7,7 @@ export const describeIfiOS = export const describeIfAndroid = device.getPlatform() === 'android' ? describe : describe.skip; -async function scrollUntilVisible(id: string, scrollViewId: string) { +export async function scrollUntilVisible(id: string, scrollViewId: string) { await waitFor(element(by.id(id))) .toBeVisible() .whileElement(by.id(scrollViewId)) @@ -72,18 +72,18 @@ export async function getElementAttributes( testLabel: string, ): Promise { const attrs = await element(by.label(testLabel)).getAttributes(); - + if ('elements' in attrs) { throw new Error( - `Multiple elements (${attrs.elements.length}) found for label: "${testLabel}". ` + `Multiple elements (${attrs.elements.length}) found for label: "${testLabel}". `, ); } - + return attrs as ElementAttributes; } /** - * Performs a coordinate-based tap on iOS to interact with an element that may be + * Performs a coordinate-based tap on iOS to interact with an element that may be * obstructed by other UI layers, bypassing Detox's default visibility checks. */ export async function forceTapByLabeliOS(testLabel: string) { diff --git a/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts b/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts index de548d8cf2..01fba5f2fb 100644 --- a/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts +++ b/FabricExample/e2e/single-feature-tests/tabs/test-tabs-special-effects-scroll-to-top.e2e.ts @@ -1,9 +1,9 @@ import { device, expect, element, by } from 'detox'; import { + scrollUntilVisible, selectSingleFeatureTestsScreen, forceTapByLabeliOS, } from '../../e2e-utils'; - /** * Selects a tab bar item. On iOS, this uses a forced coordinate tap to * ensure the tab is selected even if it is obstructed by the iOS 26 Liquid Glass lens. @@ -16,12 +16,6 @@ async function forceSelectTabByLabel(label: string) { } } -async function scrollDown(targetId: string, scrollViewId: string) { - await waitFor(element(by.id(targetId))) - .toBeVisible() - .whileElement(by.id(scrollViewId)) - .scroll(500, 'down', NaN, 0.85); -} describe('Tabs specialEffects — scrollToTop', () => { beforeAll(async () => { await device.reloadReactNative(); @@ -44,7 +38,7 @@ describe('Tabs specialEffects — scrollToTop', () => { }); it('Tab1 (scrollToTop: true) — re-tapping active tab scrolls list back to top', async () => { - await scrollDown('tab1-item-22', 'tab1-scrollview'); + await scrollUntilVisible('tab1-item-22', 'tab1-scrollview'); await expect(element(by.id('tab1-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab1-tab-item-label'); @@ -58,7 +52,7 @@ describe('Tabs specialEffects — scrollToTop', () => { await element(by.id('tab2-tab-item')).tap(); await expect(element(by.id('tab2-item-1'))).toBeVisible(); - await scrollDown('tab2-item-22', 'tab2-scrollview'); + await scrollUntilVisible('tab2-item-22', 'tab2-scrollview'); await expect(element(by.id('tab2-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab2-tab-item-label'); @@ -70,7 +64,7 @@ describe('Tabs specialEffects — scrollToTop', () => { await element(by.id('tab3-tab-item')).tap(); await expect(element(by.id('tab3-item-1'))).toBeVisible(); - await scrollDown('tab3-item-22', 'tab3-scrollview'); + await scrollUntilVisible('tab3-item-22', 'tab3-scrollview'); await expect(element(by.id('tab3-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab3-tab-item-label'); @@ -84,7 +78,7 @@ describe('Tabs specialEffects — scrollToTop', () => { await forceSelectTabByLabel('tab1-tab-item-label'); await expect(element(by.id('tab1-item-1'))).toBeVisible(); - await scrollDown('tab1-item-22', 'tab1-scrollview'); + await scrollUntilVisible('tab1-item-22', 'tab1-scrollview'); await expect(element(by.id('tab1-item-1'))).not.toBeVisible(); await forceSelectTabByLabel('tab3-tab-item-label');