Files
iNaturalistReactNative/tests/integration/navigation/AddObsButton.test.js
Abbey Campbell 92d81d7be8 Mob 1239 obs sheet not dismissing (#3576)
* use bottom sheet api instead of returning null when hidden

* dedupe inside modal dismiss logic

* rename handleSnapPress -> openSheet

* ts fixes and split render into two branches

* fix integration test so we check for BottomSheet behavior rather than child absence

* snapshot updates + comments

* prevent hidden-state BottomSheet dismiss from triggering onPressClose

* port changes from BottomSheet to BottomSheetV2
2026-05-04 20:40:10 +02:00

133 lines
3.3 KiB
JavaScript

import { BottomSheetModal } from "@gorhom/bottom-sheet";
import { screen, userEvent } from "@testing-library/react-native";
import AddObsButton from "components/AddObsBottomSheet/AddObsButton";
import i18next from "i18next";
import React from "react";
import { renderComponent } from "tests/helpers/render";
import setStoreStateLayout from "tests/helpers/setStoreStateLayout";
const actor = userEvent.setup();
const mockDispatch = jest.fn();
jest.mock( "@react-navigation/native", () => {
const actualNav = jest.requireActual( "@react-navigation/native" );
return {
...actualNav,
useNavigation: () => ( {
dispatch: mockDispatch,
} ),
};
} );
const resetNavigation = ( name, params ) => ( {
payload: {
index: 0,
routes: [{
name: "NoBottomTabStackNavigator",
state: {
index: 0,
routes: [{
name,
params,
}],
},
}],
},
type: "RESET",
} );
beforeAll( ( ) => {
jest.useFakeTimers( );
} );
const longPress = async ( ) => {
const addObsButton = screen.getByLabelText(
i18next.t( "Add-observations" ),
);
expect( addObsButton ).toBeTruthy( );
await actor.longPress( addObsButton );
};
const showNoEvidenceOption = ( ) => {
const noEvidenceButton = screen.getByTestId(
i18next.t( "observe-without-evidence-button" ),
);
expect( noEvidenceButton ).toBeTruthy( );
return noEvidenceButton;
};
const regularPress = async ( ) => {
const addObsButton = screen.getByLabelText(
i18next.t( "Add-observations" ),
);
expect( addObsButton ).toBeTruthy( );
await actor.press( addObsButton );
};
describe( "AddObsButton", ( ) => {
it( "navigates user to AI camera", async ( ) => {
renderComponent( <AddObsButton /> );
await regularPress( );
expect( mockDispatch ).toHaveBeenCalledWith(
resetNavigation( "Camera", { camera: "AI", previousScreen: null } ),
);
} );
it( "opens model on long press", async ( ) => {
renderComponent( <AddObsButton /> );
await longPress( );
showNoEvidenceOption( );
} );
} );
describe( "with advanced user layout", ( ) => {
beforeEach( ( ) => {
setStoreStateLayout( {
isAllAddObsOptionsMode: true,
} );
} );
it( "opens AddObsBottomSheet", async ( ) => {
renderComponent( <AddObsButton /> );
await regularPress( );
showNoEvidenceOption( );
} );
it( "navigates user to obs edit with no evidence", async ( ) => {
renderComponent( <AddObsButton /> );
await regularPress( );
const noEvidenceButton = showNoEvidenceOption( );
await actor.press( noEvidenceButton );
expect( mockDispatch ).toHaveBeenCalledWith(
resetNavigation( "ObsEdit", { previousScreen: null } ),
);
} );
it( "does not open model on long press", async ( ) => {
const presentSpy = jest.spyOn( BottomSheetModal.prototype, "present" );
renderComponent( <AddObsButton /> );
await longPress( );
expect( presentSpy ).not.toHaveBeenCalled( );
presentSpy.mockRestore( );
} );
describe( "with advanced AICamera-only setting", ( ) => {
beforeEach( ( ) => {
setStoreStateLayout( {
isDefaultMode: false,
isAllAddObsOptionsMode: false,
} );
} );
it( "opens model on long press", async ( ) => {
renderComponent( <AddObsButton /> );
await longPress( );
showNoEvidenceOption( );
} );
} );
} );