Merge pull request #3295 from inaturalist/mob-722-pt1

MOB-722 Match screen unit tests part one
This commit is contained in:
Seth Peterson
2025-12-18 09:22:21 -06:00
committed by GitHub
5 changed files with 340 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
import { screen } from "@testing-library/react-native";
import AdditionalSuggestionsScroll
from "components/Match/AdditionalSuggestions/AdditionalSuggestionsScroll";
import React from "react";
import factory from "tests/factory";
import { renderComponent } from "tests/helpers/render";
describe( "AdditionalSuggestionsScroll", () => {
it( "returns null when not loading and otherSuggestions is empty", () => {
renderComponent(
<AdditionalSuggestionsScroll
otherSuggestions={[]}
suggestionsLoading={false}
onSuggestionChosen={jest.fn()}
/>
);
expect( screen.queryByText( "It might also be" ) ).toBeFalsy();
expect( screen.queryByText( "It might be one of these" ) ).toBeFalsy();
} );
it( "shows ActivityIndicator when suggestionsLoading is true", () => {
renderComponent(
<AdditionalSuggestionsScroll
otherSuggestions={[]}
suggestionsLoading
onSuggestionChosen={jest.fn()}
/>
);
expect( screen.getByRole( "progressbar" ) ).toBeVisible();
} );
it( "renders heading when noTopSuggestion is true", () => {
const suggestions = [
{
taxon: factory( "RemoteTaxon" ),
combined_score: 85
}
];
renderComponent(
<AdditionalSuggestionsScroll
noTopSuggestion
otherSuggestions={suggestions}
suggestionsLoading={false}
onSuggestionChosen={jest.fn()}
/>
);
expect( screen.getByText( "It might be one of these" ) ).toBeVisible();
} );
} );

View File

@@ -0,0 +1,45 @@
import { fireEvent, screen } from "@testing-library/react-native";
import EmptyMapSection from "components/Match/EmptyMapSection";
import React from "react";
import { renderComponent } from "tests/helpers/render";
describe( "EmptyMapSection", () => {
const mockHandleAddLocationPressed = jest.fn();
it( "displays the location indicator icon", () => {
renderComponent(
<EmptyMapSection
isFetchingLocation={false}
handleAddLocationPressed={mockHandleAddLocationPressed}
/>
);
const locationIndicator = screen.getByTestId( "Map.LocationIndicator" );
expect( locationIndicator ).toBeVisible();
} );
it( "calls handleAddLocationPressed when button is pressed", () => {
renderComponent(
<EmptyMapSection
isFetchingLocation={false}
handleAddLocationPressed={mockHandleAddLocationPressed}
/>
);
const button = screen.getByText( "ADD LOCATION FOR BETTER IDS" );
fireEvent.press( button );
expect( mockHandleAddLocationPressed ).toHaveBeenCalled();
} );
it( "shows loading state when isFetchingLocation is true", () => {
renderComponent(
<EmptyMapSection
isFetchingLocation
handleAddLocationPressed={mockHandleAddLocationPressed}
/>
);
const button = screen.getByLabelText( "Edit location" );
expect( button.props.accessibilityState.disabled ).toBe( true );
} );
} );

View File

@@ -0,0 +1,74 @@
import { fireEvent, screen } from "@testing-library/react-native";
import IconicSuggestion from "components/Match/IconicSuggestions/IconicSuggestion";
import React from "react";
import * as useTaxon from "sharedHooks/useTaxon";
import factory from "tests/factory";
import { renderComponent } from "tests/helpers/render";
const mockTaxon = factory( "LocalTaxon", {
id: 47170,
name: "actinopterygii",
preferred_common_name: "Ray-finned Fishes",
rank: "class",
rank_level: 50,
default_photo: {
url: "https://example.com/photo.jpg"
}
} );
jest.mock( "sharedHooks/useTaxon", () => ( {
__esModule: true,
default: () => ( { taxon: mockTaxon } )
} ) );
describe( "IconicSuggestion", () => {
it( "renders taxon with common name and scientific name", () => {
renderComponent( <IconicSuggestion taxon={mockTaxon} /> );
expect( screen.getByText( "Ray-finned Fishes" ) ).toBeVisible();
expect( screen.getByText( "actinopterygii" ) ).toBeVisible();
} );
it( "calls handlePress when pressed", () => {
const mockHandlePress = jest.fn();
renderComponent( <IconicSuggestion taxon={mockTaxon} handlePress={mockHandlePress} /> );
const button = screen.getByTestId( "IconicSuggestion.47170" );
fireEvent.press( button );
expect( mockHandlePress ).toHaveBeenCalled();
} );
it( "uses local taxon when fromLocal is true", () => {
const localTaxon = factory( "LocalTaxon", {
id: 3,
name: "Aves",
preferred_common_name: "Birds",
rank: "class",
rank_level: 50
} );
jest.spyOn( useTaxon, "default" ).mockImplementation( () => ( { taxon: localTaxon } ) );
renderComponent( <IconicSuggestion taxon={mockTaxon} fromLocal /> );
expect( screen.getByText( "Birds" ) ).toBeVisible();
expect( screen.getByText( "Aves" ) ).toBeVisible();
} );
it( "handles taxon without common name", () => {
const taxonWithoutCommonName = factory( "LocalTaxon", {
id: 47115,
name: "Mollusca",
preferred_common_name: undefined,
rank: "phylum",
rank_level: 60
} );
jest.spyOn( useTaxon, "default" )
.mockImplementation( () => ( { taxon: taxonWithoutCommonName } ) );
renderComponent( <IconicSuggestion taxon={taxonWithoutCommonName} /> );
expect( screen.getByText( "Mollusca" ) ).toBeVisible();
} );
} );

View File

@@ -0,0 +1,73 @@
import { screen } from "@testing-library/react-native";
import MatchHeader from "components/Match/MatchHeader";
import React from "react";
import factory from "tests/factory";
import { renderComponent } from "tests/helpers/render";
describe( "MatchHeader", () => {
it( "does not render content when topSuggestion is not provided", () => {
renderComponent( <MatchHeader /> );
expect( screen.queryByText( /observed/i ) ).toBeFalsy();
expect( screen.queryByText( /Confidence/i ) ).toBeFalsy();
} );
it( "displays high confidence message for species", () => {
const topSuggestion = {
combined_score: 95,
taxon: factory( "LocalTaxon", { rank_level: 10 } )
};
renderComponent( <MatchHeader topSuggestion={topSuggestion} /> );
expect( screen.getByText( "You observed this species" ) ).toBeVisible();
} );
it( "displays high confidence message for taxa above species", () => {
const topSuggestion = {
combined_score: 95,
taxon: factory( "LocalTaxon", { rank_level: 20 } )
};
renderComponent( <MatchHeader topSuggestion={topSuggestion} /> );
expect( screen.getByText( "You observed a species in this group" ) ).toBeVisible();
expect( screen.getByText( "95%" ) ).toBeVisible();
expect( screen.getByText( "Confidence" ) ).toBeVisible();
} );
it( "displays likely confidence message for species", () => {
const topSuggestion = {
combined_score: 75,
taxon: factory( "LocalTaxon", { rank_level: 10 } )
};
renderComponent( <MatchHeader topSuggestion={topSuggestion} /> );
expect( screen.getByText( "You likely observed this species" ) ).toBeVisible();
} );
it( "displays may have observed message", () => {
const topSuggestion = {
combined_score: 30,
taxon: factory( "LocalTaxon", { rank_level: 10 } )
};
renderComponent( <MatchHeader topSuggestion={topSuggestion} /> );
expect( screen.getByText( "You may have observed this species" ) ).toBeVisible();
} );
it( "hides observation status when hideObservationStatus is true", () => {
const topSuggestion = {
combined_score: 87.5,
taxon: factory( "LocalTaxon", { rank_level: 10 } )
};
renderComponent( <MatchHeader topSuggestion={topSuggestion} hideObservationStatus /> );
expect( screen.queryByText( "You observed this species" ) ).toBeFalsy();
expect( screen.queryByText( "87.5%" ) ).toBeFalsy();
expect( screen.queryByText( "Confidence" ) ).toBeFalsy();
} );
} );

View File

@@ -0,0 +1,96 @@
import { fireEvent, screen } from "@testing-library/react-native";
import SuggestionsResult from "components/Match/AdditionalSuggestions/SuggestionsResult";
import React from "react";
import factory from "tests/factory";
import { renderComponent } from "tests/helpers/render";
describe( "SuggestionsResult", () => {
it( "renders and displays taxon name, image, and confidence", () => {
const apiTaxon = factory( "RemoteTaxon", {
id: 745,
name: "Silphium perfoliatum",
preferred_common_name: "Cup Plant",
rank: "species",
rank_level: 10,
representative_photo: {
url: "https://example.com/cupplant.jpg"
}
} );
renderComponent(
<SuggestionsResult
taxon={apiTaxon}
confidence={87}
forcedHeight={0}
/>
);
expect( screen.getByText( "Cup Plant" ) ).toBeVisible();
expect( screen.getByText( "Silphium perfoliatum" ) ).toBeVisible();
expect( screen.getByText( "87% confidence" ) ).toBeVisible();
expect( screen.getByTestId( "SuggestionsResult.745.photo" ) ).toBeVisible();
} );
it( "handles non valid Realm taxon and returns null", () => {
const invalidTaxon = factory( "LocalTaxon", {
id: 746,
name: "Silphium laciniatum"
} );
invalidTaxon.isValid = () => false;
renderComponent(
<SuggestionsResult
taxon={invalidTaxon}
confidence={75}
forcedHeight={0}
/>
);
expect( screen.queryByText( "Silphium laciniatum" ) ).toBeFalsy();
} );
it( "calls handlePress when pressed", () => {
const mockHandlePress = jest.fn();
const taxon = factory( "RemoteTaxon", { id: 747 } );
renderComponent(
<SuggestionsResult
taxon={taxon}
confidence={95}
handlePress={mockHandlePress}
forcedHeight={0}
/>
);
const button = screen.getByTestId( "SuggestionsResult.747" );
fireEvent.press( button );
expect( mockHandlePress ).toHaveBeenCalled();
} );
it( "calls updateMaxHeight with measured height on layout", () => {
const mockUpdateMaxHeight = jest.fn();
const taxon = factory( "RemoteTaxon", { id: 748 } );
renderComponent(
<SuggestionsResult
taxon={taxon}
confidence={60}
updateMaxHeight={mockUpdateMaxHeight}
forcedHeight={0}
/>
);
const layoutView = screen.getByTestId( "SuggestionsResult.748" ).parent;
fireEvent( layoutView, "layout", {
nativeEvent: {
layout: {
height: 120
}
}
} );
expect( mockUpdateMaxHeight ).toHaveBeenCalledWith( 120 );
} );
} );