Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add-e2e-main-navigation-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"live-mobile": minor
---

Add E2E test infrastructure for main navigation (Wallet 4.0 and legacy)
28 changes: 28 additions & 0 deletions apps/ledger-live-mobile/e2e/mocks/react-native-blur.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/**
* Mock for @sbaiahmed1/react-native-blur used during E2E (Detox) builds.
*
* BlurView's UIViewPropertyAnimator sets an NSNull delegate on CAAnimation,
* which crashes DetoxSync's animation tracking on iOS.
* Replacing native blur components with plain Views avoids the crash while
* keeping the rest of the UI intact.
*/
const React = require("react");
const { View } = require("react-native");

const passthrough = React.forwardRef((props, ref) => {
const { style, children } = props;
return React.createElement(View, { ref, style }, children);
});

passthrough.displayName = "BlurViewMock";

module.exports = {
BlurView: passthrough,
VibrancyView: passthrough,
LiquidGlassView: passthrough,
LiquidGlassContainer: passthrough,
ProgressiveBlurView: passthrough,
BlurSwitch: passthrough,
default: passthrough,
};
9 changes: 9 additions & 0 deletions apps/ledger-live-mobile/rspack.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ const withRozeniteUrlFix = rozeniteConfig => {
};
};

const isDetoxBuild = process.env.DETOX === "1" || (process.env.ENVFILE || "").includes("mock");

const detoxAliases = isDetoxBuild
? {
"@sbaiahmed1/react-native-blur": path.resolve(__dirname, "e2e/mocks/react-native-blur.js"),
}
: {};

const hermesNonCompatibleDependencies = ["@polkadot/types-codec"];

/**
Expand Down Expand Up @@ -140,6 +148,7 @@ export default withRozeniteUrlFix(
modules: nodeModulesPaths,
alias: {
...buildTsAlias(tsconfig.compilerOptions.paths),
...detoxAliases,
// Packages with malformed exports field (missing "." subpath) - resolve to browser entry
"@aptos-labs/aptos-client": resolvePackageFile(
"@aptos-labs/aptos-client",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import EarnLiveAppNavigator from "../EarnLiveAppNavigator";
import { Tab } from "./tabNavigator";
import type { LegacyTabNavigatorProps } from "./types";

const LEGACY_TAB_TEST_IDS: Partial<Record<string, string>> = {
[NavigatorName.Portfolio]: "tab-bar-portfolio",
[NavigatorName.Earn]: "tab-bar-earn",
[NavigatorName.Web3HubTab]: "tab-bar-discover",
[NavigatorName.Discover]: "tab-bar-discover",
[NavigatorName.MyLedger]: "TabBarManager",
};

export function LegacyTabNavigator({
tabBar,
screenOptions,
Expand All @@ -31,6 +39,7 @@ export function LegacyTabNavigator({
options={{
headerShown: false,
tabBarIcon: props => <PortfolioTabIcon {...props} />,
tabBarButtonTestID: LEGACY_TAB_TEST_IDS[NavigatorName.Portfolio],
}}
listeners={({ navigation }) => ({
tabPress: e => {
Expand All @@ -53,10 +62,11 @@ export function LegacyTabNavigator({
<TabIcon
Icon={IconsLegacy.LendMedium}
i18nKey={earnYieldLabel}
testID="tab-bar-earn"
testID={LEGACY_TAB_TEST_IDS[NavigatorName.Earn]}
{...props}
/>
),
tabBarButtonTestID: LEGACY_TAB_TEST_IDS[NavigatorName.Earn],
}}
listeners={({ navigation }) => ({
tabPress: e => {
Expand Down Expand Up @@ -101,6 +111,7 @@ export function LegacyTabNavigator({
tabBarIcon: props => (
<TabIcon Icon={IconsLegacy.PlanetMedium} i18nKey="tabs.discover" {...props} />
),
tabBarButtonTestID: LEGACY_TAB_TEST_IDS[NavigatorName.Web3HubTab],
}}
listeners={({ navigation }) => ({
tabPress: e => {
Expand All @@ -120,6 +131,7 @@ export function LegacyTabNavigator({
tabBarIcon: props => (
<TabIcon Icon={IconsLegacy.PlanetMedium} i18nKey="tabs.discover" {...props} />
),
tabBarButtonTestID: LEGACY_TAB_TEST_IDS[NavigatorName.Discover],
}}
listeners={({ navigation }) => ({
tabPress: e => {
Expand All @@ -139,7 +151,7 @@ export function LegacyTabNavigator({
options={{
headerShown: false,
tabBarIcon: props => <ManagerTabIcon {...props} />,
tabBarButtonTestID: "TabBarManager",
tabBarButtonTestID: LEGACY_TAB_TEST_IDS[NavigatorName.MyLedger],
}}
listeners={({ navigation }) => ({
tabPress: e => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const MainTabBarView: React.FC<MainTabBarViewProps> = ({

return (
<Animated.View
testID="w40-tab-bar"
entering={FadeInDown}
exiting={FadeOutDown}
pointerEvents="box-none"
Expand Down Expand Up @@ -50,6 +51,7 @@ export const MainTabBarView: React.FC<MainTabBarViewProps> = ({
label={item.label}
icon={item.icon}
activeIcon={item.activeIcon}
testID={item.testID}
/>
))}
</TabBar>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { BottomTabBarProps } from "@react-navigation/bottom-tabs";
import type { TabBarItemProps } from "@ledgerhq/lumen-ui-rnative";

export type TabItemConfig = Pick<TabBarItemProps, "value" | "label" | "icon" | "activeIcon">;
export type TabItemConfig = Pick<
TabBarItemProps,
"value" | "label" | "icon" | "activeIcon" | "testID"
>;

export interface MainTabBarViewProps {
readonly activeRouteName: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ const TAB_ICONS: Partial<Record<string, TabIconConfig>> = {
[NavigatorName.Earn]: { icon: Chart5, activeIcon: Chart5Fill },
[NavigatorName.CardTab]: { icon: CreditCard, activeIcon: CreditCardFill },
};

const TAB_TEST_IDS: Partial<Record<string, string>> = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use it for some test id declaration accross the PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok i will update

[NavigatorName.Portfolio]: "w40-tab-home",
[NavigatorName.Swap]: "w40-tab-swap",
[NavigatorName.Earn]: "w40-tab-earn",
[NavigatorName.CardTab]: "w40-tab-card",
};

export const useMainTabBarViewModel = ({
state,
navigation,
Expand All @@ -43,6 +51,7 @@ export const useMainTabBarViewModel = ({
state.routes.map(route => ({
value: route.name,
label: t(LABELKEY_MAP[route.name] ?? route.name),
testID: TAB_TEST_IDS[route.name],
...TAB_ICONS[route.name],
})),
[state.routes, t],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export const PortfolioScreen = ({ navigation }: NavigationProps) => {
<>
<CheckLanguageAvailability />
<CheckTermOfUseUpdate />
<Animated.View style={{ flex: 1 }}>
<Animated.View testID="portfolio-screen" style={{ flex: 1 }}>
<RefreshableCollapsibleHeaderFlatList
data={data}
renderItem={renderItem<React.JSX.Element>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React from "react";
import HeaderBackButton from "LLM/components/Navigation/HeaderBackButton";
import HeaderTitle from "LLM/components/Navigation/HeaderTitle";

export const HEADER_BACK_BUTTON_TEST_ID = "header-back-button";

export const wallet40HeaderOptions = {
headerShown: true,
headerTitle: () => <HeaderTitle titleKey="manager.title" />,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => <HeaderBackButton testID={HEADER_BACK_BUTTON_TEST_ID} />,
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const EarnV2Webview = ({
};

return (
<View style={{ flex: 1, overflow: "visible" }}>
<View testID="earn-screen" style={{ flex: 1, overflow: "visible" }}>
{isPtxUiV2 && !hideMainNavigator && <EarnBackground scrollY={scrollY} />}
<View style={{ flex: 1, zIndex: 1 }} pointerEvents="box-none">
{manifest ? (
Expand Down
2 changes: 1 addition & 1 deletion apps/ledger-live-mobile/src/screens/PTX/Earn/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function Earn({ route }: Props) {
/** V1: no background */
if (manifest) {
return (
<View style={{ flex: 1 }}>
<View testID="earn-screen" style={{ flex: 1 }}>
<Container>
<TrackScreen category="EarnDashboard" name="Earn" />
<EarnWebview manifest={manifest} inputs={webviewInputs} />
Expand Down
2 changes: 1 addition & 1 deletion apps/ledger-live-mobile/src/screens/Portfolio/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ function PortfolioScreen({ navigation }: NavigationProps) {
<>
<CheckLanguageAvailability />
<CheckTermOfUseUpdate />
<Animated.View style={{ flex: 1 }}>
<Animated.View testID="portfolio-screen" style={{ flex: 1 }}>
<RefreshableCollapsibleHeaderFlatList
data={data}
renderItem={renderItem<React.JSX.Element>}
Expand Down
6 changes: 6 additions & 0 deletions e2e/mobile/page/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import StakePage from "./trade/stake.page";
import SwapPage from "./trade/swap.page";
import SwapLiveAppPage from "./liveApps/swapLiveApp";
import WalletTabNavigatorPage from "./wallet/walletTabNavigator.page";
import MainNavigationPage from "./wallet/mainNavigation.page";
import CeloManageAssetsPage from "./trade/celoManageAssets.page";
import TransferMenuDrawer from "./wallet/transferMenu.drawer";
import BuySellPage from "./trade/buySell.page";
Expand Down Expand Up @@ -76,6 +77,7 @@ export class Application {
private swapLiveAppInstance = lazyInit(SwapLiveAppPage);
private swapPageInstance = lazyInit(SwapPage);
private walletTabNavigatorPageInstance = lazyInit(WalletTabNavigatorPage);
private mainNavigationPageInstance = lazyInit(MainNavigationPage);
private celoManageAssetsPageInstance = lazyInit(CeloManageAssetsPage);
private TransferMenuDrawerInstance = lazyInit(TransferMenuDrawer);
private buySellPageInstance = lazyInit(BuySellPage);
Expand Down Expand Up @@ -195,6 +197,10 @@ export class Application {
return this.walletTabNavigatorPageInstance();
}

public get mainNavigation() {
return this.mainNavigationPageInstance();
}

public get celoManageAssets() {
return this.celoManageAssetsPageInstance();
}
Expand Down
Loading
Loading