feat: add onboarding carousel (#2285)

Note that offsetting the onboarding images ended up being a bit hard. We're
mostly doing so with a cropped version of one of the images.

Closes #1906

Also tried to de-flake some tests:

* Use fake timers when possible
* Ensure time travel helper doesn't un-fake our timers
* Wait for time travel helper to finish so changes don't happen outside of
  act
* Stop mocking useCurrentUser in integration tests; that's app code and should
  not be mocked when integrating all parts of the app; instead use signIn /
  signOut helpers
* Remove unnecessary direct uses of act()
* Mocked some inatjs calls to prevent React Query complaints about undefined
  query return values
* Close onboarding before all e2e tests

---------

Co-authored-by: Ken-ichi Ueda <kenichi.ueda@gmail.com>
This commit is contained in:
budowski
2024-11-05 04:03:55 +08:00
committed by GitHub
parent a4d2c7ca24
commit 7b8c88c84d
36 changed files with 1582 additions and 160 deletions

View File

@@ -3,6 +3,7 @@ import {
} from "detox";
import { iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers";
import closeOnboarding from "./sharedFlows/closeOnboarding";
import deleteObservation from "./sharedFlows/deleteObservation";
import signIn from "./sharedFlows/signIn";
import switchPowerMode from "./sharedFlows/switchPowerMode";
@@ -15,6 +16,7 @@ describe( "AICamera", () => {
it(
"should open the ai camera, take photo, select a suggestion, upload and delete observation",
async () => {
await closeOnboarding( );
/*
/ 1. Sign in
*/

View File

@@ -0,0 +1,21 @@
import {
by,
element,
waitFor
} from "detox";
const VISIBILITY_TIMEOUT = 10_000;
export default async function closeOnboarding( ) {
const loginText = element( by.id( "log-in-to-iNaturalist-button.text" ) );
await waitFor( loginText ).toExist().withTimeout( VISIBILITY_TIMEOUT );
// If we can see MyObs, we don't need to close the onboarding
if ( loginText.visible ) {
return Promise.resolve( );
}
const closeOnboardingButton = element(
by.label( "Close" ).withAncestor( by.id( "OnboardingCarousel" ) )
);
await waitFor( closeOnboardingButton ).toBeVisible( ).withTimeout( VISIBILITY_TIMEOUT );
return closeOnboardingButton.tap( );
}

View File

@@ -1,6 +1,7 @@
import { device } from "detox";
import { iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers";
import closeOnboarding from "./sharedFlows/closeOnboarding";
import signIn from "./sharedFlows/signIn";
describe( "Shared flow", () => {
@@ -8,6 +9,7 @@ describe( "Shared flow", () => {
beforeEach( async () => iNatE2eBeforeEach( device ) );
it( "should sign in the test user", async () => {
await closeOnboarding( );
await signIn( );
} );
} );

View File

@@ -3,6 +3,7 @@ import {
} from "detox";
import { iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers";
import closeOnboarding from "./sharedFlows/closeOnboarding";
import deleteObservation from "./sharedFlows/deleteObservation";
import signIn from "./sharedFlows/signIn";
import switchPowerMode from "./sharedFlows/switchPowerMode";
@@ -57,6 +58,7 @@ describe( "Signed in user", () => {
}
it( "should create an observation, add a comment, and delete the observation", async () => {
await closeOnboarding( );
/*
/ 1. Sign in
*/

View File

@@ -7,12 +7,14 @@ import {
} from "detox";
import { iNatE2eBeforeAll, iNatE2eBeforeEach } from "./helpers";
import closeOnboarding from "./sharedFlows/closeOnboarding";
describe( "Signed out user", () => {
beforeAll( async ( ) => iNatE2eBeforeAll( device ) );
beforeEach( async ( ) => iNatE2eBeforeEach( device ) );
it( "should start at My Observations with log in text", async () => {
await closeOnboarding( );
const loginText = element( by.id( "log-in-to-iNaturalist-button.text" ) );
await waitFor( loginText ).toBeVisible( ).withTimeout( 10000 );
await expect( loginText ).toBeVisible( );