From 1a5e4f2c55a29d1f3168e0a9ca1a6ba49aca105d Mon Sep 17 00:00:00 2001 From: lkuchno Date: Fri, 24 Apr 2026 11:15:43 +0200 Subject: [PATCH 1/6] chore(test): test-tabs-events screen with scenario --- .../tests/single-feature-tests/tabs/index.ts | 2 + .../tabs/test-tabs-events/index.tsx | 119 ++++++++++++++++++ .../tabs/test-tabs-events/scenario.md | 115 +++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx create mode 100644 apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md diff --git a/apps/src/tests/single-feature-tests/tabs/index.ts b/apps/src/tests/single-feature-tests/tabs/index.ts index 4703ab3fb9..fc5c888012 100644 --- a/apps/src/tests/single-feature-tests/tabs/index.ts +++ b/apps/src/tests/single-feature-tests/tabs/index.ts @@ -14,6 +14,7 @@ import TestTabsPreventNativeSelection from './test-tabs-prevent-native-selection import TestTabsStaleStateUpdateRejection from './test-tabs-stale-update-rejection'; import TestTabsTabBarMinimizeBehavior from './test-tabs-tab-bar-minimize-behavior-ios'; import TestTabsTabBarControllerMode from './test-tabs-tab-bar-controller-mode-ios'; +import testTabsEvents from './test-tabs-events'; const scenarios = { BottomAccessoryScenario, @@ -30,6 +31,7 @@ const scenarios = { TestTabsStaleStateUpdateRejection, TestTabsTabBarMinimizeBehavior, TestTabsTabBarControllerMode, + testTabsEvents, }; const TabsScenarioGroup: ScenarioGroup = { diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx new file mode 100644 index 0000000000..1f5e5ea965 --- /dev/null +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx @@ -0,0 +1,119 @@ +import React, { useCallback } from 'react'; +import { StyleSheet, Text } from 'react-native'; +import type { ScenarioDescription } from '@apps/tests/shared/helpers'; +import { createScenario } from '@apps/tests/shared/helpers'; +import { + TabsContainer, + type TabRouteConfig, + DEFAULT_TAB_ROUTE_OPTIONS, + useTabsNavigationContext, +} from '@apps/shared/gamma/containers/tabs'; +import { CenteredLayoutView } from '@apps/shared/CenteredLayoutView'; +import { ToastProvider, useToast } from '@apps/shared/'; +import { Colors } from '@apps/shared/styling'; + +const scenarioDescription: ScenarioDescription = { + name: 'Tabs lifecycle events', + key: 'test-tabs-events', + details: + 'Verifies onWillAppear, onDidAppear, onWillDisappear, onDidDisappear fire in the correct order when switching tabs.', + platforms: ['ios', 'android'], +}; + +function TabScreen() { + const { routeKey } = useTabsNavigationContext(); + + return ( + + + {routeKey} + + Switch tabs to trigger lifecycle events + + ); +} + +function AppContents() { + const toast = useToast(); + + const makeCallbacks = useCallback( + (tabName: string) => ({ + onWillAppear: () => + toast.push({ + message: `${tabName}: onWillAppear`, + backgroundColor: Colors.GreenLight100, + }), + onDidAppear: () => + toast.push({ + message: `${tabName}: onDidAppear`, + backgroundColor: Colors.BlueLight100, + }), + onWillDisappear: () => + toast.push({ + message: `${tabName}: onWillDisappear`, + backgroundColor: Colors.NavyLight60, + }), + onDidDisappear: () => + toast.push({ + message: `${tabName}: onDidDisappear`, + backgroundColor: Colors.NavyLight100, + }), + }), + [toast], + ); + + const TAB_CONFIGS: TabRouteConfig[] = [ + { + name: 'TabA', + Component: TabScreen, + options: { + ...DEFAULT_TAB_ROUTE_OPTIONS, + title: 'Tab A', + ...makeCallbacks('TabA'), + }, + }, + { + name: 'TabB', + Component: TabScreen, + options: { + ...DEFAULT_TAB_ROUTE_OPTIONS, + title: 'Tab B', + ...makeCallbacks('TabB'), + }, + }, + { + name: 'TabC', + Component: TabScreen, + options: { + ...DEFAULT_TAB_ROUTE_OPTIONS, + title: 'Tab C', + ...makeCallbacks('TabC'), + }, + }, + ]; + + return ; +} + +export function App() { + return ( + + + + ); +} + +export default createScenario(App, scenarioDescription); + +const styles = StyleSheet.create({ + tabLabel: { + fontSize: 24, + fontWeight: 'bold', + marginBottom: 8, + }, + tabHint: { + color: '#666', + fontSize: 13, + textAlign: 'center', + }, +}); diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md new file mode 100644 index 0000000000..903bb3b5dd --- /dev/null +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md @@ -0,0 +1,115 @@ +# Test Scenario: Tabs lifecycle events + +## Details + +**Description:** Verifies that `onWillAppear`, `onDidAppear`, +`onWillDisappear`, and `onDidDisappear` fire in the correct order on tab +switches, covering happy-path transitions, re-tapping the active tab, and +rapid switching. + +**OS test creation version:** iOS: 18.6 and 26.2, Android: 18.6. + +## E2E test + +Other: On going research + +## Prerequisites + +- iOS simulator or device (iPhone) +- Android emulator or device + +## Note + +- All four events should fire on every tab switch. The expected order for + a switch from Tab X to Tab Y is: + 1. `TabY: onWillDisappear` + 2. `TabX: onWillAppear` + 3. `TabY: onDidDisappear` + 4. `TabX: onDidAppear` +- Toasts stack and dismiss automatically; observe each toast color and + label as it appears. To dismiss a toast manually, tap it. +- Re-tapping the currently active tab must not fire any lifecycle events. + +## Steps + +### Baseline + +1. Launch the app and navigate to **Tabs lifecycle events**. + +- [ ] Expected: Three tabs are visible in the tab bar: **Tab A**, **Tab B**, + and **Tab C**. **Tab A** is selected. Two toasts + appear for the initial Tab A appearance: + - `TabA: onWillAppear` + - `TabA: onDidAppear` + +--- + +### Tab A → Tab B transition + +2. Tap **Tab B** in the tab bar. + +- [ ] Expected: The content area switches to show "TabB". Four toast + notifications appear in sequence: + - `TabB: onWillAppear` (green background) + - `TabA: onWillDisappear` (light navy background) + - `TabB: onDidAppear` (light blue background) + - `TabA: onDidDisappear` (dark navy background) + +--- + +### Tab B → Tab C transition + +3. Tap **Tab C** in the tab bar. + +- [ ] Expected: The content area switches to show "TabC". Four toast + notifications appear in sequence: + - `TabC: onWillAppear` (green background) + - `TabB: onWillDisappear` (light navy background) + - `TabC: onDidAppear` (light blue background) + - `TabB: onDidDisappear` (dark navy background) + +--- + +### Tab C → Tab A transition + +4. Tap **Tab A** in the tab bar. + +- [ ] Expected: The content area switches to show "TabA". Four toast + notifications appear in sequence: + - `TabA: onWillAppear` (green background) + - `TabC: onWillDisappear` (light navy background) + - `TabA: onDidAppear` (light blue background) + - `TabC: onDidDisappear` (dark navy background) + +--- + +### Re-tapping the active tab (edge case) + +5. With **Tab A** selected, tap **Tab A** again in the tab bar. + +- [ ] Expected: The content area does not change. No toast notifications + appear. No lifecycle events fire for a tap on the already-active tab. + +--- + +### Rapid tab switching (edge case) + +6. Tap **Tab B**, then immediately tap **Tab C** before the toasts from + the previous step have finished dismissing. + +- [ ] Expected: Both transitions complete. Toasts from the B→C transition + appear after the A→B toasts. The final selected + tab is **Tab C** and its content area shows "TabC". No events are + missing or duplicated — all eight toasts from both transitions are + eventually shown. + +--- + +### Full round-trip verification + +7. From **Tab C**, tap **Tab A**, then **Tab B**, then **Tab C**. + +- [ ] Expected: Each tab switch produces exactly four toasts (will/did + disappear for the leaving tab, will/did appear for the arriving tab). + After three switches, twelve toasts in total have been fired. The final + selected tab is **Tab C**. From 6c2a437073cd49c80703fe25cdf57b3f32a51ba6 Mon Sep 17 00:00:00 2001 From: lkuchno Date: Fri, 24 Apr 2026 12:46:41 +0200 Subject: [PATCH 2/6] scenario correction as the order of events is different in ios and android --- .../tabs/test-tabs-events/scenario.md | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md index 903bb3b5dd..277b34e07f 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md @@ -21,11 +21,17 @@ Other: On going research ## Note - All four events should fire on every tab switch. The expected order for - a switch from Tab X to Tab Y is: - 1. `TabY: onWillDisappear` - 2. `TabX: onWillAppear` - 3. `TabY: onDidDisappear` - 4. `TabX: onDidAppear` + a switch between TabX and TabY depends on platform + For iOS: + 1. `TabY: onWillAppear` + 2. `TabX: onWillDisappear` + 3. `TabY: onDidAppear` + 4. `TabX: onDidDisappear` + For Android: + 1. `TabX: onWillDisappear` + 2. `TabX: onDidDisappear` + 3. `TabY: onWillAppear` + 4. `TabY: onDidAppear` - Toasts stack and dismiss automatically; observe each toast color and label as it appears. To dismiss a toast manually, tap it. - Re-tapping the currently active tab must not fire any lifecycle events. @@ -49,7 +55,7 @@ Other: On going research 2. Tap **Tab B** in the tab bar. - [ ] Expected: The content area switches to show "TabB". Four toast - notifications appear in sequence: + notifications appear in order specific platform: - `TabB: onWillAppear` (green background) - `TabA: onWillDisappear` (light navy background) - `TabB: onDidAppear` (light blue background) @@ -62,7 +68,7 @@ Other: On going research 3. Tap **Tab C** in the tab bar. - [ ] Expected: The content area switches to show "TabC". Four toast - notifications appear in sequence: + notifications appear in order specific platform: - `TabC: onWillAppear` (green background) - `TabB: onWillDisappear` (light navy background) - `TabC: onDidAppear` (light blue background) @@ -75,7 +81,7 @@ Other: On going research 4. Tap **Tab A** in the tab bar. - [ ] Expected: The content area switches to show "TabA". Four toast - notifications appear in sequence: + notifications appear in order specific platform: - `TabA: onWillAppear` (green background) - `TabC: onWillDisappear` (light navy background) - `TabA: onDidAppear` (light blue background) From 1131216f2845c3a81d7f6d6e8c2a39f9834445b6 Mon Sep 17 00:00:00 2001 From: lkuchno <45803783+LKuchno@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:18:22 +0200 Subject: [PATCH 3/6] Update apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../single-feature-tests/tabs/test-tabs-events/scenario.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md index 277b34e07f..116f7a507f 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md @@ -11,7 +11,7 @@ rapid switching. ## E2E test -Other: On going research +Other: ongoing research ## Prerequisites From 7dafc96e6474bf9a194e9e8d43dd1f81d693b786 Mon Sep 17 00:00:00 2001 From: lkuchno Date: Fri, 24 Apr 2026 14:22:53 +0200 Subject: [PATCH 4/6] changes in scenario and index --- apps/src/tests/single-feature-tests/tabs/index.ts | 4 ++-- .../single-feature-tests/tabs/test-tabs-events/scenario.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/src/tests/single-feature-tests/tabs/index.ts b/apps/src/tests/single-feature-tests/tabs/index.ts index fc5c888012..15ce113de7 100644 --- a/apps/src/tests/single-feature-tests/tabs/index.ts +++ b/apps/src/tests/single-feature-tests/tabs/index.ts @@ -14,7 +14,7 @@ import TestTabsPreventNativeSelection from './test-tabs-prevent-native-selection import TestTabsStaleStateUpdateRejection from './test-tabs-stale-update-rejection'; import TestTabsTabBarMinimizeBehavior from './test-tabs-tab-bar-minimize-behavior-ios'; import TestTabsTabBarControllerMode from './test-tabs-tab-bar-controller-mode-ios'; -import testTabsEvents from './test-tabs-events'; +import TestTabsEvents from './test-tabs-events'; const scenarios = { BottomAccessoryScenario, @@ -31,7 +31,7 @@ const scenarios = { TestTabsStaleStateUpdateRejection, TestTabsTabBarMinimizeBehavior, TestTabsTabBarControllerMode, - testTabsEvents, + TestTabsEvents, }; const TabsScenarioGroup: ScenarioGroup = { diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md index 277b34e07f..60ddbb8ec5 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md @@ -55,7 +55,7 @@ Other: On going research 2. Tap **Tab B** in the tab bar. - [ ] Expected: The content area switches to show "TabB". Four toast - notifications appear in order specific platform: + notifications appear in a platform-specific order: - `TabB: onWillAppear` (green background) - `TabA: onWillDisappear` (light navy background) - `TabB: onDidAppear` (light blue background) @@ -68,7 +68,7 @@ Other: On going research 3. Tap **Tab C** in the tab bar. - [ ] Expected: The content area switches to show "TabC". Four toast - notifications appear in order specific platform: + notifications appear in a platform-specific order: - `TabC: onWillAppear` (green background) - `TabB: onWillDisappear` (light navy background) - `TabC: onDidAppear` (light blue background) @@ -81,7 +81,7 @@ Other: On going research 4. Tap **Tab A** in the tab bar. - [ ] Expected: The content area switches to show "TabA". Four toast - notifications appear in order specific platform: + notifications appear in a platform-specific order: - `TabA: onWillAppear` (green background) - `TabC: onWillDisappear` (light navy background) - `TabA: onDidAppear` (light blue background) From d6891d7a81676d2160533df266500e79ef81b1dc Mon Sep 17 00:00:00 2001 From: lkuchno Date: Mon, 27 Apr 2026 10:19:19 +0200 Subject: [PATCH 5/6] corrects --- .../tabs/test-tabs-events/index.tsx | 59 +++++++++-------- .../tabs/test-tabs-events/scenario.md | 66 +++++++++++++------ 2 files changed, 77 insertions(+), 48 deletions(-) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx index 1f5e5ea965..10fff5446f 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/index.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { StyleSheet, Text } from 'react-native'; import type { ScenarioDescription } from '@apps/tests/shared/helpers'; import { createScenario } from '@apps/tests/shared/helpers'; @@ -16,7 +16,7 @@ const scenarioDescription: ScenarioDescription = { name: 'Tabs lifecycle events', key: 'test-tabs-events', details: - 'Verifies onWillAppear, onDidAppear, onWillDisappear, onDidDisappear fire in the correct order when switching tabs.', + 'Verify lifecycle events (onWillAppear, etc.) fire on tab switch', platforms: ['ios', 'android'], }; @@ -62,35 +62,38 @@ function AppContents() { [toast], ); - const TAB_CONFIGS: TabRouteConfig[] = [ - { - name: 'TabA', - Component: TabScreen, - options: { - ...DEFAULT_TAB_ROUTE_OPTIONS, - title: 'Tab A', - ...makeCallbacks('TabA'), + const TAB_CONFIGS = useMemo( + () => [ + { + name: 'TabA', + Component: TabScreen, + options: { + ...DEFAULT_TAB_ROUTE_OPTIONS, + title: 'Tab A', + ...makeCallbacks('TabA'), + }, }, - }, - { - name: 'TabB', - Component: TabScreen, - options: { - ...DEFAULT_TAB_ROUTE_OPTIONS, - title: 'Tab B', - ...makeCallbacks('TabB'), + { + name: 'TabB', + Component: TabScreen, + options: { + ...DEFAULT_TAB_ROUTE_OPTIONS, + title: 'Tab B', + ...makeCallbacks('TabB'), + }, }, - }, - { - name: 'TabC', - Component: TabScreen, - options: { - ...DEFAULT_TAB_ROUTE_OPTIONS, - title: 'Tab C', - ...makeCallbacks('TabC'), + { + name: 'TabC', + Component: TabScreen, + options: { + ...DEFAULT_TAB_ROUTE_OPTIONS, + title: 'Tab C', + ...makeCallbacks('TabC'), + }, }, - }, - ]; + ], + [makeCallbacks], + ); return ; } diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md index 2693b4f0c4..b0c91d685c 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md @@ -32,8 +32,10 @@ Other: ongoing research 2. `TabX: onDidDisappear` 3. `TabY: onWillAppear` 4. `TabY: onDidAppear` -- Toasts stack and dismiss automatically; observe each toast color and - label as it appears. To dismiss a toast manually, tap it. +- Toasts stack and dismiss automatically. To dismiss a toast manually, + tap it. Toast background colors by event type: + `onWillAppear` — green, `onWillDisappear` — light navy, + `onDidAppear` — light blue, `onDidDisappear` — dark navy. - Re-tapping the currently active tab must not fire any lifecycle events. ## Steps @@ -54,12 +56,20 @@ Other: ongoing research 2. Tap **Tab B** in the tab bar. -- [ ] Expected: The content area switches to show "TabB". Four toast - notifications appear in a platform-specific order: - - `TabB: onWillAppear` (green background) - - `TabA: onWillDisappear` (light navy background) - - `TabB: onDidAppear` (light blue background) - - `TabA: onDidDisappear` (dark navy background) +- [ ] Expected: The content area switches to show "TabB". Four toasts + appear in the following platform-specific order: + + **iOS:** + 1. `TabB: onWillAppear` + 2. `TabA: onWillDisappear` + 3. `TabB: onDidAppear` + 4. `TabA: onDidDisappear` + + **Android:** + 1. `TabA: onWillDisappear` + 2. `TabA: onDidDisappear` + 3. `TabB: onWillAppear` + 4. `TabB: onDidAppear` --- @@ -67,12 +77,20 @@ Other: ongoing research 3. Tap **Tab C** in the tab bar. -- [ ] Expected: The content area switches to show "TabC". Four toast - notifications appear in a platform-specific order: - - `TabC: onWillAppear` (green background) - - `TabB: onWillDisappear` (light navy background) - - `TabC: onDidAppear` (light blue background) - - `TabB: onDidDisappear` (dark navy background) +- [ ] Expected: The content area switches to show "TabC". Four toasts + appear in the following platform-specific order: + + **iOS:** + 1. `TabC: onWillAppear` + 2. `TabB: onWillDisappear` + 3. `TabC: onDidAppear` + 4. `TabB: onDidDisappear` + + **Android:** + 1. `TabB: onWillDisappear` + 2. `TabB: onDidDisappear` + 3. `TabC: onWillAppear` + 4. `TabC: onDidAppear` --- @@ -80,12 +98,20 @@ Other: ongoing research 4. Tap **Tab A** in the tab bar. -- [ ] Expected: The content area switches to show "TabA". Four toast - notifications appear in a platform-specific order: - - `TabA: onWillAppear` (green background) - - `TabC: onWillDisappear` (light navy background) - - `TabA: onDidAppear` (light blue background) - - `TabC: onDidDisappear` (dark navy background) +- [ ] Expected: The content area switches to show "TabA". Four toasts + appear in the following platform-specific order: + + **iOS:** + 1. `TabA: onWillAppear` + 2. `TabC: onWillDisappear` + 3. `TabA: onDidAppear` + 4. `TabC: onDidDisappear` + + **Android:** + 1. `TabC: onWillDisappear` + 2. `TabC: onDidDisappear` + 3. `TabA: onWillAppear` + 4. `TabA: onDidAppear` --- From 6a443051090f1792bc28e0e9e2939bc4fb9835a7 Mon Sep 17 00:00:00 2001 From: lkuchno Date: Mon, 27 Apr 2026 11:00:55 +0200 Subject: [PATCH 6/6] list change --- .../single-feature-tests/tabs/test-tabs-events/scenario.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md index b0c91d685c..eab030493e 100644 --- a/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md +++ b/apps/src/tests/single-feature-tests/tabs/test-tabs-events/scenario.md @@ -22,11 +22,13 @@ Other: ongoing research - All four events should fire on every tab switch. The expected order for a switch between TabX and TabY depends on platform + For iOS: 1. `TabY: onWillAppear` 2. `TabX: onWillDisappear` 3. `TabY: onDidAppear` 4. `TabX: onDidDisappear` + For Android: 1. `TabX: onWillDisappear` 2. `TabX: onDidDisappear`