Files
paseo/packages/app/e2e/support/recovery-app.tsx
T
Mohamed Boudra 4006f974fb Reload to the project picker after an app error (#4598)
* fix(app): reload to the project picker after a render error

Keep the recovery boundary above the router so Reload starts a new navigation tree at the picker instead of remounting the failed workspace. Preserve saved layouts and normal startup restoration.

* test(app): exercise reload through fixture routes
2026-09-11 08:09:05 +02:00

56 lines
1.9 KiB
TypeScript

// Test-only entry: the production recovery boundary and Expo router with failing routes.
import "../../src/styles/unistyles";
// oxlint-disable-next-line import/no-unassigned-import -- Match the Metro web entry runtime.
import "@expo/metro-runtime";
import { registerRootComponent } from "expo";
import { Link, Redirect, Stack, type Href } from "expo-router";
import { useCallback, useState, type ComponentProps } from "react";
import { Button, Text, View } from "react-native";
import { RootRouter } from "../../src/root-app";
const screenOptions = { headerShown: false };
function Layout() {
return <Stack screenOptions={screenOptions} />;
}
// Fixture routes are absent from Expo's generated production route types.
function Startup() {
return <Redirect href={"/broken" as Href} />;
}
function BrokenWorkspace(): never {
throw new Error("Workspace recovery fixture");
}
function Picker() {
return (
<View>
<Text>Project picker</Text>
<Link href={"/healthy" as Href}>Open healthy workspace</Link>
</View>
);
}
function HealthyWorkspace() {
const [broken, setBroken] = useState(false);
const breakWorkspace = useCallback(() => setBroken(true), []);
if (broken) return <BrokenWorkspace />;
return (
<View>
<Text>Healthy workspace</Text>
<Button title="Break this workspace" onPress={breakWorkspace} />
</View>
);
}
const screens = {
"./_layout.tsx": { default: Layout },
"./index.tsx": { default: Startup },
"./broken.tsx": { default: BrokenWorkspace },
"./open-project.tsx": { default: Picker },
"./healthy.tsx": { default: HealthyWorkspace },
};
const context: ComponentProps<typeof RootRouter>["context"] = Object.assign(
(key: string) => screens[key as keyof typeof screens],
{ keys: () => Object.keys(screens), resolve: (key: string) => key, id: "recovery-fixture" },
);
function RecoveryApp() {
return <RootRouter context={context} />;
}
registerRootComponent(RecoveryApp);