diff --git a/.changeset/verify-expo-map-unmapped-flows.md b/.changeset/verify-expo-map-unmapped-flows.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/verify-expo-map-unmapped-flows.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.claude/skills/verify-clerk-expo/SKILL.md b/.claude/skills/verify-clerk-expo/SKILL.md index 683b6839710..972f0ce130a 100644 --- a/.claude/skills/verify-clerk-expo/SKILL.md +++ b/.claude/skills/verify-clerk-expo/SKILL.md @@ -154,7 +154,7 @@ The test app shows the home again when a full-screen AuthView or a custom form c The test app has a screen or a small flow of its own only where the native views cannot prove a thing. The custom sign-in and sign-up forms drive `useSignIn` and `useSignUp`. The test app reads the `@clerk/expo` token cache once, as the app starts and before Clerk has loaded, and the `Token cache` screen says whether a client token was kept from the last launch. `Sign in with a logo` opens the home's modal AuthView with a React Native view as its `logo`. The `Embedded profile` screen is UserProfileView inline with one custom page, `isDismissible={false}`, and `onHostBack`. The `Native modules` screen has one button for `useSignInWithGoogle` and one for `useBiometricCredentials`, each with its result as text. The test app looks and behaves as an app does for a real user. When a change needs a flow that no native view covers, add a screen that a real app would have, and assert on the outcome as a user sees it. -On iOS, locate nodes of the native views with the SDK's identifiers, such as `screen.getByTestId('clerk.auth.start.identifier')`. The clerk-android release that `@clerk/expo-native-components` pins sets the same `clerk.*` names as resource ids, but `specs/native.ts` still finds the Android native views by text. The home has `e2e.*` testIDs, which `host.app` holds, and the test app's other screens have `verify.*` testIDs, on both platforms. All of these identifiers are internal test hooks, not public API, and they can change. Every spec keeps at least one exact assertion on an identifier or on visible text. To assert on the text of a node, use `await expect(locator).toHaveText('...')`. +On iOS, locate nodes of the native views with the SDK's identifiers, such as `screen.getByTestId('clerk.auth.start.identifier')`. The clerk-android release that `@clerk/expo-native-components` pins sets the same `clerk.*` names as resource ids, but `specs/native.ts` still finds the Android native views by text. The home has `e2e.*` testIDs, which `host.app` holds, and the test app's other screens have `verify.*` testIDs, on both platforms, except the Native modules screen, whose testIDs have no prefix ([Native modules](features/native-modules.md)). All of these identifiers are internal test hooks, not public API, and they can change. Every spec keeps at least one exact assertion on an identifier or on visible text. To assert on the text of a node, use `await expect(locator).toHaveText('...')`. Every test starts on the standard settings. A test that needs other settings calls `host.useSettings({ config, environment? })`, and the CLI puts every leaf it changed back when the test ends. [Test instances](references/instances.md) has the call, the restore, and the leaves that tests often change. To see which settings are on or off, run `integration/expo-native/bin/control-clerk-expo settings `, such as `settings auth_multi_factor`. diff --git a/.claude/skills/verify-clerk-expo/features/README.md b/.claude/skills/verify-clerk-expo/features/README.md index ae3cf077e27..50a87d0594c 100644 --- a/.claude/skills/verify-clerk-expo/features/README.md +++ b/.claude/skills/verify-clerk-expo/features/README.md @@ -60,6 +60,6 @@ Each feature file starts with an H1 title and one paragraph describing the user- - [Native modules](./native-modules.md) covers `useSignInWithGoogle` opening the native Google sign-in, a cancel of it on iOS, and on Android when back closes Google's page, and `useBiometricCredentials` reporting what its native module found on the device. - [Update required](./update-required.md) covers the update screen for a signed-in and a signed-out user on a build below the minimum, the same session returning once the minimum is lowered, and a build at the minimum, on both platforms, and it lists the states no spec reaches. -Not mapped yet: SSO through `useSSO` (no real OAuth on simulators), sign-in and sign-up in Account Portal through `useHostedAuth` from `@clerk/expo/hosted-auth`, which opens a browser that no spec drives and the test app has no button for (`packages/expo/src/hooks/useHostedAuth.ts`), a Google or Apple native sign-in with a real account, passkeys, enrolling or using a biometric (no associated domains or Secure Enclave on the simulator), session tasks in the native views, and AuthView's `onHostBack` and `logoMaxHeight`, which the test app passes to no AuthView (`packages/expo-native-components/src/AuthView.tsx`). +Not mapped yet: SSO through `useSSO` (no real OAuth on simulators), sign-in and sign-up in Account Portal through `useHostedAuth` from `@clerk/expo/hosted-auth`, which opens a browser that no spec drives and the test app has no button for (`packages/expo/src/hooks/useHostedAuth.ts`), a Google or Apple native sign-in with a real account, passkeys, enrolling or using a biometric (no associated domains or Secure Enclave on the simulator), session tasks in the native views, sign-up and phone sign-in through the native AuthView (`mode` `signUp` or the default `signInOrUp`), which no spec drives, the native profile's flows past the email under `Manage account`: adding or removing an email address, a phone number, or a connected account, the `Security` screens (password, MFA, biometric credential, and deleting the account), and `Add account` and `Switch account`, which the UserButton reaches and no spec drives, an inline UserProfileView that can be dismissed, with `onDismiss` (`packages/expo-native-components/src/UserProfileView.tsx`), `useLocalCredentials` from `@clerk/expo/local-credentials` (deprecated, and it needs an enrolled biometric), the experimental offline resource cache (`__experimental_resourceCache`, `packages/expo/src/resource-cache/`), which the test app does not use, and AuthView's `onHostBack` and `logoMaxHeight`, which the test app passes to no AuthView (`packages/expo-native-components/src/AuthView.tsx`). Organizations have no page, because a user of the test app has no way to reach organization UI. This holds for the native components only. `@clerk/expo/web` exports the clerk-js OrganizationProfile, OrganizationSwitcher, OrganizationList, and CreateOrganization for Expo web, but the test app runs native only. `@clerk/expo-native-components` exports AuthView, UserButton, and UserProfileView and no OrganizationSwitcher or OrganizationProfileView. The profile that the UserButton opens lists `Manage account`, `Security`, `Add account`, and `Sign out`, with `Switch account` once a second session exists, and no organization row, in the pinned clerk-ios and clerk-android releases, though the standard settings turn organizations on. The one organization screen that a native view shows is a session task in AuthView, choose or create an organization, which needs `force_organization_selection` on. The harness seeds users, sign-in tickets, and, through `host.seedOrganization`, organizations whose members hold one of the harness roles. It cannot seed invitations, so no spec can reach a choose-organization task that lists an invitation. Today such a state can be shown only with a local patch that is not committed, and the description of the pull request that shows it says so. diff --git a/.claude/skills/verify-clerk-expo/features/user-button-and-profile.md b/.claude/skills/verify-clerk-expo/features/user-button-and-profile.md index e20cb1c129c..53a7a939dfb 100644 --- a/.claude/skills/verify-clerk-expo/features/user-button-and-profile.md +++ b/.claude/skills/verify-clerk-expo/features/user-button-and-profile.md @@ -31,7 +31,7 @@ Preconditions: ## Gotchas - The UserButton is `clerk.userButton.profile` on iOS and the accessibility label `Open user profile` on Android (`nativeUserButton` in `specs/native.ts`). -- Profile rows have no stable identifier on Android, and on iOS the profile that the UserButton opens is inside a sheet, so the specs find the rows by text (`Manage account`, `Sign out`). +- The pinned clerk-android release sets the profile rows' `clerk.userProfile.row.*` names as resource ids under UserProfileView, but Android specs find native views by text, and on iOS the profile that the UserButton opens is inside a sheet, so `nativeProfile` in `specs/native.ts` finds the rows by text (`Manage account`, `Sign out`). - A seeded user has no name, so the profile header shows only the avatar. The email appears under `Manage account`. - Open the profile from the UserButton, as a user does. Use the `embeddedProfile` screen for `onHostBack` and for custom pages, which the test app passes only to its inline UserProfileView. The UserButton also takes custom pages through `userProfileProps.customPages`, and no spec covers that. No spec covers a row with `href`, which opens a URL instead of React Native content, a row's `placement` among Clerk's rows, or a page in `customDestinations` that a custom page pushes with `useUserProfileCustomPageNavigation().push` (`packages/expo-native-components/src/UserProfileCustomPages.tsx`). - Tap the profile's Back button with `tapProfileBack` from `specs/native.ts`, which taps the middle of its frame. On Android the label `Back` is on a group that holds the button, and `locator.tap()` on it fails with "no parent-owned touch point".