diff --git a/src/api/error.js b/src/api/error.js
index 80e1031cd..09b492ae7 100644
--- a/src/api/error.js
+++ b/src/api/error.js
@@ -43,10 +43,10 @@ async function handleError( e: Object, options: Object = {} ): Object {
if ( typeof ( options.onApiError ) === "function" ) {
options.onApiError( error );
}
- // Default to throw errors. We almost never want handle supress an error at
+ // Default to throw errors. We almost never want supress an error at
// this low level
if ( options.throw === false ) {
- return null;
+ return error;
}
throw error;
}
diff --git a/src/components/Camera/ARCamera/hooks/usePredictions.js b/src/components/Camera/ARCamera/hooks/usePredictions.js
index 6b5708834..eea5fb53c 100644
--- a/src/components/Camera/ARCamera/hooks/usePredictions.js
+++ b/src/components/Camera/ARCamera/hooks/usePredictions.js
@@ -3,6 +3,7 @@
import {
useState
} from "react";
+import { useIconicTaxa } from "sharedHooks";
const usePredictions = ( ): Object => {
const [result, setResult] = useState( null );
@@ -11,22 +12,27 @@ const usePredictions = ( ): Object => {
const [fps, setFPS] = useState( 1 );
const [numStoredResults, setNumStoredResults] = useState( 4 );
const [cropRatio, setCropRatio] = useState( 1 );
+ const iconicTaxa = useIconicTaxa( );
const handleTaxaDetected = cvResult => {
- console.log( "[DEBUG usePredictions.js] cvResult: ", cvResult );
if ( cvResult && !modelLoaded ) {
setModelLoaded( true );
}
let prediction = null;
- const { predictions } = cvResult;
- predictions.sort( ( a, b ) => a.rank_level - b.rank_level );
- if ( predictions.length > 0 ) {
- const finestPrediction = predictions[0];
+ const { predictions: branch } = cvResult;
+ branch.sort( ( a, b ) => a.rank_level - b.rank_level );
+ const branchIDs = branch.map( t => t.taxon_id );
+ if ( branch.length > 0 ) {
+ const finestPrediction = branch[0];
+ // Try to find a known iconic taxon in the model results so we can show
+ // an icon if we can't show a photo
+ const iconicTaxon = iconicTaxa?.find( t => branchIDs.indexOf( t.id ) >= 0 );
prediction = {
taxon: {
rank_level: finestPrediction.rank_level,
id: finestPrediction.taxon_id,
- name: finestPrediction.name
+ name: finestPrediction.name,
+ iconic_taxon_name: iconicTaxon?.name
},
score: finestPrediction.score
};
diff --git a/src/components/SharedComponents/DisplayTaxonName.js b/src/components/SharedComponents/DisplayTaxonName.js
index 27d18482f..a16122811 100644
--- a/src/components/SharedComponents/DisplayTaxonName.js
+++ b/src/components/SharedComponents/DisplayTaxonName.js
@@ -137,7 +137,7 @@ const DisplayTaxonName = ( {
return (
diff --git a/src/components/SharedComponents/ObservationsFlashList/ObsImage.js b/src/components/SharedComponents/ObservationsFlashList/ObsImage.js
index f9f1d635d..725b788da 100644
--- a/src/components/SharedComponents/ObservationsFlashList/ObsImage.js
+++ b/src/components/SharedComponents/ObservationsFlashList/ObsImage.js
@@ -1,7 +1,7 @@
// @flow
import classNames from "classnames";
import { IconicTaxonIcon } from "components/SharedComponents";
-import { Image } from "components/styledComponents";
+import { Image, View } from "components/styledComponents";
import type { Node } from "react";
import React from "react";
@@ -35,29 +35,36 @@ const ObsImage = ( {
}: Props ): Node => {
const noImg = !uri?.uri;
+ const iconicTaxon = (
+
+ );
+
if ( noImg ) {
- return (
-
- );
+ return iconicTaxon;
}
return (
-
+
+
+ {iconicTaxon}
+
+
+
);
};
diff --git a/src/components/SharedComponents/TaxonResult.js b/src/components/SharedComponents/TaxonResult.js
index af36dafe8..67ec4e96b 100644
--- a/src/components/SharedComponents/TaxonResult.js
+++ b/src/components/SharedComponents/TaxonResult.js
@@ -2,7 +2,11 @@
import { useNavigation } from "@react-navigation/native";
import classnames from "classnames";
-import { DisplayTaxonName, INatIconButton } from "components/SharedComponents";
+import {
+ ActivityIndicator,
+ DisplayTaxonName,
+ INatIconButton
+} from "components/SharedComponents";
import ObsImagePreview from "components/SharedComponents/ObservationsFlashList/ObsImagePreview";
import { Pressable, View } from "components/styledComponents";
import type { Node } from "react";
@@ -39,7 +43,7 @@ const TaxonResult = ( {
handleCheckmarkPress,
handlePress,
showCheckmark = true,
- taxon: taxonResult,
+ taxon: taxonProp,
testID,
white = false
}: Props ): Node => {
@@ -50,13 +54,13 @@ const TaxonResult = ( {
// network requests for useTaxon instead of making individual API calls.
// right now, this fetches a single taxon at a time on AR camera &
// a short list of taxa from offline Suggestions
- const localTaxon = useTaxon( taxonResult, fetchRemote );
- const taxon = fromLocal
+ const { taxon: localTaxon, isLoading } = useTaxon( taxonProp, fetchRemote );
+ const usableTaxon = fromLocal
? localTaxon
- : taxonResult;
- const taxonImage = { uri: taxon?.default_photo?.url };
+ : taxonProp;
+ const taxonImage = { uri: usableTaxon.default_photo?.url };
- const navToTaxonDetails = () => navigation.navigate( "TaxonDetails", { id: taxon.id } );
+ const navToTaxonDetails = () => navigation.navigate( "TaxonDetails", { id: usableTaxon.id } );
return (
-
- {( confidence && confidencePosition === "photo" ) && (
-
-
-
- )}
+
+ {
+ isLoading
+ ? (
+
+ )
+ : (
+
+ )
+ }
+ {( confidence && confidencePosition === "photo" ) && (
+
+
+
+ )}
+
{( confidence && confidencePosition === "text" ) && (
@@ -136,7 +149,7 @@ const TaxonResult = ( {
? theme.colors.onSecondary
: theme.colors.secondary
}
- onPress={() => handleCheckmarkPress( taxon )}
+ onPress={() => handleCheckmarkPress( usableTaxon )}
accessibilityLabel={t( "Checkmark" )}
accessibilityHint={t( "Add-this-ID" )}
testID={`${testID}.checkmark`}
diff --git a/src/realmModels/Taxon.js b/src/realmModels/Taxon.js
index c1f0f9462..ccca8bc26 100644
--- a/src/realmModels/Taxon.js
+++ b/src/realmModels/Taxon.js
@@ -1,5 +1,4 @@
import { Realm } from "@realm/react";
-import safeRealmWrite from "sharedHelpers/safeRealmWrite";
import Photo from "./Photo";
@@ -107,15 +106,6 @@ class Taxon extends Realm.Object {
static uri = item => ( item && item.default_photo ) && { uri: item.default_photo.url };
- static saveRemoteTaxon = async ( remoteTaxon, realm ) => {
- if ( remoteTaxon ) {
- const localTaxon = Taxon.mapApiToRealm( remoteTaxon, realm );
- safeRealmWrite( realm, ( ) => {
- realm.create( "Taxon", localTaxon, "modified" );
- }, "saving remote taxon in Taxon" );
- }
- };
-
static schema = {
name: "Taxon",
primaryKey: "id",
@@ -136,7 +126,8 @@ class Taxon extends Realm.Object {
rank: "string?",
rank_level: "float?",
isIconic: "bool?",
- iconic_taxon_name: "string?"
+ iconic_taxon_name: "string?",
+ _synced_at: "date?"
}
};
}
diff --git a/src/realmModels/index.js b/src/realmModels/index.js
index 4534adca3..14d06f2d6 100644
--- a/src/realmModels/index.js
+++ b/src/realmModels/index.js
@@ -28,7 +28,7 @@ export default {
User,
Vote
],
- schemaVersion: 46,
+ schemaVersion: 47,
path: `${RNFS.DocumentDirectoryPath}/db.realm`,
// https://github.com/realm/realm-js/pull/6076 embedded constraints
migrationOptions: {
diff --git a/src/sharedHooks/useIconicTaxa.js b/src/sharedHooks/useIconicTaxa.js
index fbd6a28a2..b59284600 100644
--- a/src/sharedHooks/useIconicTaxa.js
+++ b/src/sharedHooks/useIconicTaxa.js
@@ -7,7 +7,8 @@ import { useAuthenticatedQuery, useIsConnected } from "sharedHooks";
const { useRealm } = RealmContext;
-const useIconicTaxa = ( { reload }: Object ): Object => {
+const useIconicTaxa = ( options: { reload: boolean } = { reload: false } ): Object => {
+ const { reload } = options;
const realm = useRealm( );
const isConnected = useIsConnected( );
const [isUpdatingRealm, setIsUpdatingRealm] = useState( );
@@ -23,10 +24,11 @@ const useIconicTaxa = ( { reload }: Object ): Object => {
if ( iconicTaxa?.length > 0 && !isUpdatingRealm ) {
setIsUpdatingRealm( true );
safeRealmWrite( realm, ( ) => {
- iconicTaxa.forEach( taxa => {
+ iconicTaxa.forEach( taxon => {
realm.create( "Taxon", {
- ...taxa,
- isIconic: true
+ ...taxon,
+ isIconic: true,
+ _synced_at: new Date( )
}, "modified" );
} );
}, "modifying iconic taxa in useIconicTaxa" );
diff --git a/src/sharedHooks/useTaxon.js b/src/sharedHooks/useTaxon.js
index f2098352a..937c27dac 100644
--- a/src/sharedHooks/useTaxon.js
+++ b/src/sharedHooks/useTaxon.js
@@ -3,30 +3,67 @@
import { fetchTaxon } from "api/taxa";
import { RealmContext } from "providers/contexts";
import Taxon from "realmModels/Taxon";
+import safeRealmWrite from "sharedHelpers/safeRealmWrite";
import { useAuthenticatedQuery } from "sharedHooks";
const { useRealm } = RealmContext;
+const ONE_WEEK_MS = (
+ 1000 // ms / s
+ * 60 // s / min
+ * 60 // min / hr
+ * 24 // hr / day
+ * 7 // day / wk
+);
+
const useTaxon = ( taxon: Object, fetchRemote: boolean = true ): Object => {
const realm = useRealm( );
- const existingTaxon = taxon.id && realm.objectForPrimaryKey( "Taxon", taxon?.id );
+ const localTaxon = taxon.id && realm.objectForPrimaryKey( "Taxon", taxon.id );
+
+ const canFetchTaxon = !!taxon?.id;
+ const localTaxonNeedsSync = (
+ // Definitely sync if there's no local copy
+ !localTaxon
+ || (
+ // Sync if the local copy hasn't been synced in a week
+ localTaxon._synced_at && ( Date.now( ) - localTaxon._synced_at > ONE_WEEK_MS )
+ )
+ );
+ const enabled = canFetchTaxon && fetchRemote && localTaxonNeedsSync;
const {
- data: remoteTaxon
+ data: remoteTaxon,
+ isLoading
} = useAuthenticatedQuery(
["fetchTaxon", taxon?.id],
optsWithAuth => fetchTaxon( taxon.id, { fields: Taxon.TAXON_FIELDS }, optsWithAuth ),
{
- enabled: !!( taxon?.id && fetchRemote )
+ enabled
}
);
- if ( !existingTaxon && remoteTaxon ) {
- Taxon.saveRemoteTaxon( remoteTaxon, realm );
+ const mappedRemoteTaxon = remoteTaxon
+ ? Taxon.mapApiToRealm( remoteTaxon, realm )
+ : null;
+
+ if ( localTaxonNeedsSync && mappedRemoteTaxon ) {
+ safeRealmWrite( realm, ( ) => {
+ realm.create(
+ "Taxon",
+ { ...mappedRemoteTaxon, _synced_at: new Date( ) },
+ "modified"
+ );
+ }, "saving remote taxon in useTaxon" );
}
- return existingTaxon || taxon;
+ // Local is best, local-ish version of remote will be available sooner, use
+ // whatever was passed in as a last resort
+ return {
+ taxon: localTaxon || mappedRemoteTaxon || taxon,
+ // Apparently useQuery isLoading is true if the query is disabled
+ isLoading: enabled && isLoading
+ };
};
export default useTaxon;
diff --git a/tests/factories/LocalTaxon.js b/tests/factories/LocalTaxon.js
index ef0f45345..8eeddbf4e 100644
--- a/tests/factories/LocalTaxon.js
+++ b/tests/factories/LocalTaxon.js
@@ -1,10 +1,10 @@
import { define } from "factoria";
export default define( "LocalTaxon", faker => ( {
+ _synced_at: faker.date.past( ),
id: faker.number.int( ),
name: faker.person.fullName( ),
preferred_common_name: faker.person.fullName( ),
rank: "species",
- rank_level: 10,
- taxon_photos: []
+ rank_level: 10
} ) );
diff --git a/tests/helpers/render.js b/tests/helpers/render.js
index b6ae217db..d5b84586f 100644
--- a/tests/helpers/render.js
+++ b/tests/helpers/render.js
@@ -23,7 +23,7 @@ const queryClient = new QueryClient( {
}
} );
-function renderComponent( component, update = null ) {
+function renderComponent( component, update = null, renderOptions = {} ) {
const renderMethod = update || render;
return renderMethod(
@@ -36,7 +36,8 @@ function renderComponent( component, update = null ) {
-
+ ,
+ renderOptions
);
}
@@ -82,9 +83,47 @@ async function renderAppWithObservations(
await screen.findByTestId( `MyObservations.obsListItem.${observations[0].uuid}` );
}
+/**
+ * Render a hook within a component
+ *
+ * Port of equivalent in react-testing-library
+ * (https://github.com/testing-library/react-testing-library/blob/edb6344d578a8c224daf0cd6e2984f36cc6e8d86/src/pure.js#L264C1-L290C2),
+ * but using our renderComponent
+ */
+function renderHook( renderCallback, options = {} ) {
+ const { initialProps, ...renderOptions } = options;
+ const result = React.createRef( );
+
+ const TestComponent = ( { renderCallbackProps } ) => {
+ // eslint-disable-next-line testing-library/render-result-naming-convention
+ const pendingResult = renderCallback( renderCallbackProps );
+
+ React.useEffect( ( ) => {
+ result.current = pendingResult;
+ } );
+
+ return null;
+ };
+
+ const { rerender: baseRerender, unmount } = renderComponent(
+ ,
+ null,
+ renderOptions
+ );
+
+ function rerender( rerenderCallbackProps ) {
+ return baseRerender(
+
+ );
+ }
+
+ return { result, rerender, unmount };
+}
+
export {
renderApp,
renderAppWithComponent,
renderAppWithObservations,
- renderComponent
+ renderComponent,
+ renderHook
};
diff --git a/tests/integration/sharedHooks/useTaxon.test.js b/tests/integration/sharedHooks/useTaxon.test.js
index 4215f7fbd..409652e28 100644
--- a/tests/integration/sharedHooks/useTaxon.test.js
+++ b/tests/integration/sharedHooks/useTaxon.test.js
@@ -1,8 +1,32 @@
-import { renderHook } from "@testing-library/react-native";
+import { waitFor } from "@testing-library/react-native";
+import inatjs from "inaturalistjs";
import safeRealmWrite from "sharedHelpers/safeRealmWrite";
import { useTaxon } from "sharedHooks";
-import factory from "tests/factory";
+import factory, { makeResponse } from "tests/factory";
import faker from "tests/helpers/faker";
+import { renderHook } from "tests/helpers/render";
+import setupUniqueRealm from "tests/helpers/uniqueRealm";
+
+// UNIQUE REALM SETUP
+const mockRealmIdentifier = __filename;
+const { mockRealmModelsIndex, uniqueRealmBeforeAll, uniqueRealmAfterAll } = setupUniqueRealm(
+ mockRealmIdentifier
+);
+jest.mock( "realmModels/index", ( ) => mockRealmModelsIndex );
+jest.mock( "providers/contexts", ( ) => {
+ const originalModule = jest.requireActual( "providers/contexts" );
+ return {
+ __esModule: true,
+ ...originalModule,
+ RealmContext: {
+ ...originalModule.RealmContext,
+ useRealm: ( ) => global.mockRealms[mockRealmIdentifier]
+ }
+ };
+} );
+beforeAll( uniqueRealmBeforeAll );
+afterAll( uniqueRealmAfterAll );
+// /UNIQUE REALM SETUP
const mockRemoteTaxon = factory( "RemoteTaxon", {
default_photo: {
@@ -10,25 +34,33 @@ const mockRemoteTaxon = factory( "RemoteTaxon", {
}
} );
-jest.mock( "sharedHooks/useAuthenticatedQuery", () => ( {
- __esModule: true,
- default: ( ) => ( {
- data: mockRemoteTaxon
- } )
-} ) );
-
const mockTaxon = factory( "LocalTaxon", {
+ _syncedAt: faker.date.recent( { days: 1 } ),
+ default_photo: {
+ url: faker.image.url( )
+ }
+} );
+const mockOutdatedTaxon = factory( "LocalTaxon", {
+ _syncedAt: faker.date.recent( { days: 1, refDate: "2024-01-01" } ),
default_photo: {
url: faker.image.url( )
}
} );
describe( "useTaxon", ( ) => {
+ beforeAll( async () => {
+ jest.useFakeTimers( );
+ } );
+ beforeEach( ( ) => {
+ jest.restoreAllMocks( );
+ inatjs.taxa.fetch.mockResolvedValue( makeResponse( [mockRemoteTaxon] ) );
+ } );
+
describe( "with local taxon", ( ) => {
- beforeEach( async ( ) => {
+ beforeEach( ( ) => {
// Write mock taxon to realm
- safeRealmWrite( global.realm, ( ) => {
- global.realm.create( "Taxon", mockTaxon, "modified" );
+ safeRealmWrite( global.mockRealms[mockRealmIdentifier], ( ) => {
+ global.mockRealms[mockRealmIdentifier].create( "Taxon", mockTaxon, "modified" );
}, "write mock taxon, useTaxon test" );
} );
@@ -40,23 +72,73 @@ describe( "useTaxon", ( ) => {
describe( "when there is a local taxon with taxon id", ( ) => {
it( "should return local taxon with default photo", ( ) => {
const { result } = renderHook( ( ) => useTaxon( mockTaxon ) );
- expect( result.current ).toHaveProperty( "default_photo" );
- expect( result.current.default_photo.url ).toEqual( mockTaxon.default_photo.url );
+ expect( inatjs.taxa.fetch ).not.toHaveBeenCalled( );
+ const { taxon: resultTaxon } = result.current;
+ expect( resultTaxon ).toHaveProperty( "default_photo" );
+ expect( resultTaxon.default_photo.url ).toEqual( mockTaxon.default_photo.url );
+ } );
+
+ it( "should request a taxon from the API if the local copy is out of date", async ( ) => {
+ safeRealmWrite( global.mockRealms[mockRealmIdentifier], ( ) => {
+ global.mockRealms[mockRealmIdentifier].create( "Taxon", mockOutdatedTaxon, "modified" );
+ }, "write mock outdated taxon, useTaxon test" );
+ renderHook( ( ) => useTaxon( mockOutdatedTaxon ) );
+ await waitFor( ( ) => expect( inatjs.taxa.fetch ).toHaveBeenCalled( ) );
} );
} );
} );
describe( "when there is no local taxon with taxon id", ( ) => {
beforeEach( async ( ) => {
- safeRealmWrite( global.realm, ( ) => {
- global.realm.deleteAll( );
+ safeRealmWrite( global.mockRealms[mockRealmIdentifier], ( ) => {
+ global.mockRealms[mockRealmIdentifier].deleteAll( );
}, "delete all realm, useTaxon test" );
} );
- it( "should make an API call and return passed in taxon when fetchRemote is enabled", ( ) => {
- const taxonId = faker.number.int( );
- const { result } = renderHook( ( ) => useTaxon( { id: taxonId }, true ) );
- expect( result.current ).not.toHaveProperty( "default_photo" );
+ describe( "with fetchRemote: true", ( ) => {
+ it( "should request the taxon from the API", async ( ) => {
+ expect(
+ global.mockRealms[mockRealmIdentifier].objectForPrimaryKey( "Taxon", mockTaxon.id )
+ ).toBeNull( );
+ renderHook( ( ) => useTaxon( mockTaxon ) );
+ await waitFor( ( ) => expect( inatjs.taxa.fetch ).toHaveBeenCalled( ) );
+ } );
+
+ it( "should return the argument taxon if request fails", ( ) => {
+ // I don't love this. While it kind of mocks at the edge of the code
+ // we need to integrate, it doesn't test out API error handling code.
+ // I tried mocking inatjs to make it throw, but that always seems to
+ // result in a failure in the test, even though useQuery should catch
+ // those errors. ~~~kueda20240305
+ jest.mock( "@tanstack/react-query", () => ( {
+ useQuery: jest.fn( ( ) => ( {
+ error: { }
+ } ) )
+ } ) );
+ const partialTaxon = { id: faker.number.int( ), foo: "bar" };
+ const { result } = renderHook( ( ) => useTaxon( partialTaxon ) );
+ expect( result.current.taxon.foo ).toEqual( "bar" );
+ jest.unmock( "@tanstack/react-query" );
+ } );
+
+ it( "should return a taxon like a local taxon record if the request succeeds", async ( ) => {
+ const { result } = renderHook( ( ) => useTaxon( { id: mockTaxon.id } ) );
+ await waitFor( ( ) => expect( inatjs.taxa.fetch ).toHaveBeenCalled( ) );
+ expect( result.current.taxon ).toHaveProperty( "default_photo" );
+ } );
+ } );
+
+ describe( "with fetchRemote: false", ( ) => {
+ it( "should not call the API and return passed in taxon", ( ) => {
+ const taxonId = faker.number.int( );
+ expect(
+ global.mockRealms[mockRealmIdentifier].objectForPrimaryKey( "Taxon", taxonId )
+ ).toBeNull( );
+ const { result } = renderHook( ( ) => useTaxon( { id: taxonId, foo: "bar" }, false ) );
+ expect( inatjs.taxa.fetch ).not.toHaveBeenCalled( );
+ expect( result.current.taxon ).not.toHaveProperty( "default_photo" );
+ expect( result.current.taxon.foo ).toEqual( "bar" );
+ } );
} );
} );
} );
diff --git a/tests/unit/components/Camera/ARCamera.test.js b/tests/unit/components/Camera/ARCamera.test.js
index 4f03d5ffc..b4ae52701 100644
--- a/tests/unit/components/Camera/ARCamera.test.js
+++ b/tests/unit/components/Camera/ARCamera.test.js
@@ -35,7 +35,7 @@ jest.mock( "sharedHooks/useAuthenticatedQuery", () => ( {
jest.mock( "sharedHooks/useTaxon", () => ( {
__esModule: true,
- default: () => mockLocalTaxon
+ default: () => ( { taxon: mockLocalTaxon } )
} ) );
const mockModelLoaded = {
@@ -120,9 +120,11 @@ describe( "AR Camera", ( ) => {
it( "displays iconic taxon icon if taxon does not exist in realm", ( ) => {
jest.spyOn( useTaxon, "default" ).mockImplementation( () => ( {
- ...mockLocalTaxon,
- default_photo: {
- url: null
+ taxon: {
+ ...mockLocalTaxon,
+ default_photo: {
+ url: null
+ }
}
} ) );
jest.spyOn( usePredictions, "default" ).mockImplementation( () => ( {
diff --git a/tests/unit/components/SharedComponents/ObservationsFlashList/__snapshots__/ObsGridItem.test.js.snap b/tests/unit/components/SharedComponents/ObservationsFlashList/__snapshots__/ObsGridItem.test.js.snap
index dc94ebc4e..62c14b85c 100644
--- a/tests/unit/components/SharedComponents/ObservationsFlashList/__snapshots__/ObsGridItem.test.js.snap
+++ b/tests/unit/components/SharedComponents/ObservationsFlashList/__snapshots__/ObsGridItem.test.js.snap
@@ -31,13 +31,7 @@ exports[`ObsGridItem for an observation with a photo should render 1`] = `
}
testID="MyObservations.gridItem.00000000-0000-0000-0000-000000000000"
>
-
+ >
+
+
+
+
+
+
+
+
+
( {
__esModule: true,
- default: () => mockTaxon
+ default: () => ( { taxon: mockTaxon } )
} ) );
describe( "TaxonResult", () => {
diff --git a/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap b/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap
index 56555c761..8a2fcb9a1 100644
--- a/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap
+++ b/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap
@@ -77,10 +77,7 @@ exports[`TaxonResult should render correctly 1`] = `
"alignItems": "center",
},
{
- "width": 64,
- },
- {
- "flexGrow": 1,
+ "flexShrink": 1,
},
],
]
@@ -91,49 +88,25 @@ exports[`TaxonResult should render correctly 1`] = `
[
[
{
- "maxHeight": 210,
- },
- {
- "overflow": "hidden",
- },
- {
- "position": "relative",
- },
- {
- "borderBottomLeftRadius": 8,
- "borderBottomRightRadius": 8,
- "borderTopLeftRadius": 8,
- "borderTopRightRadius": 8,
+ "width": 62,
},
{
"height": 62,
},
{
- "width": 62,
+ "justifyContent": "center",
+ },
+ {
+ "position": "relative",
},
- [
- {
- "borderBottomLeftRadius": 12,
- "borderBottomRightRadius": 12,
- "borderTopLeftRadius": 12,
- "borderTopRightRadius": 12,
- },
- ],
],
]
}
- testID="undefined.photo"
>
-
-
-
-
-
+
+
+
+
+ [
+ {
+ "position": "absolute",
+ },
+ {
+ "right": 0,
+ },
+ {
+ "paddingBottom": 4,
+ "paddingLeft": 4,
+ "paddingRight": 4,
+ "paddingTop": 4,
+ },
+ {
+ "bottom": 0,
+ },
+ ],
+ ]
+ }
+ />
+
( {
__esModule: true,
- default: () => mockTaxon
+ default: () => ( { taxon: mockTaxon } )
} ) );
const mockSuggestionsList = [{
diff --git a/tests/unit/components/Suggestions/TaxonSearch.test.js b/tests/unit/components/Suggestions/TaxonSearch.test.js
index 3fa17143b..03aec49a8 100644
--- a/tests/unit/components/Suggestions/TaxonSearch.test.js
+++ b/tests/unit/components/Suggestions/TaxonSearch.test.js
@@ -33,7 +33,7 @@ jest.mock( "sharedHooks/useTaxonSearch", () => ( {
jest.mock( "sharedHooks/useTaxon", () => ( {
__esModule: true,
- default: () => mockTaxaList[0]
+ default: () => ( { taxon: mockTaxaList[0] } )
} ) );
// react-native-paper's TextInput does a bunch of async stuff that's hard to