Files
iNaturalistReactNative/tests/unit/components/ObsDetailsDefaultMode/IdentificationSheets.test.js
Johannes Klein 43443f5cfc Consolidate ObsDetails screens (#3649)
* Create new hook shell

* Revert "Create new hook shell"

This reverts commit b6918db347.

* Copy ObsDetailsDefaultModeScreensWrapper as is to new file

* Copy ObsDetailsContainer as is into new file

* We don't need this param at this level

* Have new ObsDetailsContainer be the next child of screen

* Update props of new child and remove thereby hoisted code

* Move route param extraction into component that needs it

* Extract presentational logic into new component

* Also copy over flow types

* Also copy over flow types

* Return null if no observation

* Remove mode switch logic from navigator

* Remove no longer needed advanced mode container

* Consolidate default mode container into new one as well, and switch over default mode to show default mode UI

* Same as in advanced mode, read param where it is needed

* Remove prop

* Run the integration test on the only container

* Git mv test file and update with new import

* Move test and only keep the UI logic part being tested

* Move tests relevant for ObsDetailsScreen

* Update ObsDetailsScreen.test.js

* Update IdentificationSheets.test.js

* Remove unused screen wrapper
2026-05-27 16:27:27 +02:00

216 lines
5.9 KiB
JavaScript

import { useRoute } from "@react-navigation/native";
import { screen, waitFor } from "@testing-library/react-native";
import IdentificationSheets,
{ identReducer } from "components/ObsDetailsDefaultMode/IdentificationSheets";
import { t } from "i18next";
import React from "react";
import fetchTaxonAndSave from "sharedHelpers/fetchTaxonAndSave";
import useAuthenticatedMutation from "sharedHooks/useAuthenticatedMutation";
import factory from "tests/factory";
import { renderComponent } from "tests/helpers/render";
jest.mock( "sharedHelpers/fetchTaxonAndSave" );
jest.mock( "sharedHooks/useAuthenticatedMutation" );
jest.mock( "@react-navigation/native", () => ( {
...jest.requireActual( "@react-navigation/native" ),
useRoute: jest.fn(),
} ) );
const mockRealm = {
objectForPrimaryKey: jest.fn( () => null ),
};
jest.mock( "providers/contexts", () => ( {
RealmContext: {
useRealm: () => mockRealm,
},
} ) );
const mockUser = factory( "LocalUser" );
jest.mock( "sharedHooks/useCurrentUser", () => ( {
__esModule: true,
default: () => mockUser,
} ) );
const mockTaxon = factory( "RemoteTaxon" );
const mockObservation = factory( "LocalObservation" );
const mockMutate = jest.fn();
describe( "IdentificationSheets", () => {
beforeEach( () => {
jest.clearAllMocks();
useAuthenticatedMutation.mockImplementation( ( mutationFn, options ) => ( {
mutate: params => {
mockMutate( params );
if ( options && options.onSuccess ) {
options.onSuccess( { id: 1 } );
}
if ( options && options.onSettled ) {
options.onSettled( );
}
},
isPending: false,
} ) );
} );
const defaultProps = {
agreeIdentification: false,
closeAgreeWithIdSheet: jest.fn(),
handleCommentMutationSuccess: jest.fn(),
handleIdentificationMutationSuccess: jest.fn(),
hideAddCommentSheet: jest.fn(),
loadActivityItem: jest.fn(),
observation: mockObservation,
showAgreeWithIdSheet: false,
};
describe( "SuggestIDSheet", () => {
it( "shows SuggestIDSheet when identTaxonId is provided via route params", async () => {
useRoute.mockReturnValue( {
params: {
identTaxonId: mockTaxon.id,
uuid: mockObservation.uuid,
},
} );
fetchTaxonAndSave.mockResolvedValue( mockTaxon );
renderComponent(
<IdentificationSheets {...defaultProps} />,
);
await waitFor( () => {
expect( screen.getByText(
t( "Would-you-like-to-suggest-the-following-identification" ),
) ).toBeVisible();
} );
} );
} );
describe( "Route params", () => {
it( "fetches taxon from Realm when identTaxonId is provided", async () => {
const mockRealmTaxon = { ...mockTaxon };
mockRealm.objectForPrimaryKey.mockReturnValue( mockRealmTaxon );
useRoute.mockReturnValue( {
params: {
identTaxonId: mockTaxon.id,
uuid: mockObservation.uuid,
},
} );
renderComponent(
<IdentificationSheets {...defaultProps} />,
);
await waitFor( () => {
expect( mockRealm.objectForPrimaryKey ).toHaveBeenCalledWith(
"Taxon",
mockTaxon.id,
);
} );
expect( fetchTaxonAndSave ).not.toHaveBeenCalled();
} );
it( "fetches taxon from API when not found in Realm", async () => {
mockRealm.objectForPrimaryKey.mockReturnValue( null );
fetchTaxonAndSave.mockResolvedValue( mockTaxon );
useRoute.mockReturnValue( {
params: {
identTaxonId: mockTaxon.id,
uuid: mockObservation.uuid,
},
} );
renderComponent(
<IdentificationSheets {...defaultProps} />,
);
await waitFor( () => {
expect( fetchTaxonAndSave ).toHaveBeenCalledWith(
mockTaxon.id,
mockRealm,
);
} );
} );
} );
describe( "identReducer", () => {
const initialState = {
comment: null,
commentIsOptional: false,
showIdentBodySheet: false,
newIdentification: null,
showPotentialDisagreementSheet: false,
showSuggestIdSheet: false,
identTaxon: null,
};
it( "handles SET_NEW_IDENTIFICATION action", () => {
const testTaxon = { id: 123, name: "Test Taxon" };
const action = {
type: "SET_NEW_IDENTIFICATION",
taxon: testTaxon,
body: "Test comment",
vision: true,
};
const newState = identReducer( initialState, action );
expect( newState.newIdentification ).toEqual( {
taxon: testTaxon,
body: "Test comment",
vision: true,
} );
} );
it( "handles SUBMIT_IDENTIFICATION action", () => {
const stateWithData = {
...initialState,
showPotentialDisagreementSheet: true,
showSuggestIdSheet: true,
newIdentification: { taxon: { id: 123 } },
identTaxon: { id: 123 },
};
const action = { type: "SUBMIT_IDENTIFICATION" };
const newState = identReducer( stateWithData, action );
expect( newState.showPotentialDisagreementSheet ).toBe( false );
expect( newState.showSuggestIdSheet ).toBe( false );
expect( newState.newIdentification ).toBeNull();
expect( newState.identTaxon ).toBeNull();
} );
} );
describe( "deleted remote observation", () => {
it( "shows WarningSheet when remoteObsWasDeleted is true", async () => {
const confirmRemoteObsWasDeleted = jest.fn( );
useRoute.mockReturnValue( {
params: {
uuid: mockObservation.uuid,
},
} );
renderComponent(
<IdentificationSheets
{...defaultProps}
confirmRemoteObsWasDeleted={confirmRemoteObsWasDeleted}
remoteObsWasDeleted
/>,
);
expect(
await screen.findByText( t( "OBSERVATION-WAS-DELETED" ) ),
).toBeVisible();
expect(
screen.getByText( t( "Sorry-this-observation-was-deleted" ) ),
).toBeVisible();
} );
} );
} );