mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-05-24 08:22:26 -04:00
Restore tests removed in recent suggeston fixes (#1001)
* Restored Suggestions navigation tests * Restored SuggestionsWithSyncedObs.test.js tests * Mocked vision-camera-plugin-inatvision instead of useOfflineSuggestions * Removed unnecessarily complex object from navigation params There were a lot of issues here, but the main ones (I think) were related to rendering all the navigators and waiting for asynchronous stuff to happen before proceeding with the test.
This commit is contained in:
@@ -73,6 +73,8 @@ async function fetchTaxon( id: any, params: Object = {}, opts: Object = {} ): Pr
|
||||
try {
|
||||
const fetchParams = { ...PARAMS, ...params };
|
||||
const { results } = await inatjs.taxa.fetch( id, fetchParams, opts );
|
||||
if ( results.length === 0 ) return null;
|
||||
|
||||
return mapToLocalSchema( results[0] );
|
||||
} catch ( e ) {
|
||||
return handleError( e );
|
||||
|
||||
@@ -105,7 +105,7 @@ const ObsDetailsContainer = ( ): Node => {
|
||||
const { params } = useRoute();
|
||||
const {
|
||||
comment,
|
||||
taxonSuggested,
|
||||
suggestedTaxonId,
|
||||
uuid,
|
||||
vision
|
||||
} = params;
|
||||
@@ -310,12 +310,12 @@ const ObsDetailsContainer = ( ): Node => {
|
||||
);
|
||||
|
||||
const onIDAdded = useCallback( () => {
|
||||
if ( !taxonSuggested ) return;
|
||||
if ( !suggestedTaxonId ) return;
|
||||
|
||||
// New taxon identification added by user
|
||||
const idParams = {
|
||||
observation_id: uuid,
|
||||
taxon_id: taxonSuggested.id,
|
||||
taxon_id: suggestedTaxonId,
|
||||
vision
|
||||
};
|
||||
|
||||
@@ -328,13 +328,13 @@ const ObsDetailsContainer = ( ): Node => {
|
||||
createIdentificationMutation.mutate( { identification: idParams } );
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [taxonSuggested, uuid, vision] );
|
||||
}, [suggestedTaxonId, uuid, vision] );
|
||||
|
||||
useEffect( () => {
|
||||
if ( !taxonSuggested ) return;
|
||||
if ( !suggestedTaxonId ) return;
|
||||
|
||||
onIDAdded();
|
||||
}, [onIDAdded, taxonSuggested] );
|
||||
}, [onIDAdded, suggestedTaxonId] );
|
||||
|
||||
useEffect( ( ) => {
|
||||
if (
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
isFuture,
|
||||
parseISO
|
||||
} from "date-fns";
|
||||
import { difference } from "lodash";
|
||||
import { difference, isNil } from "lodash";
|
||||
import type { Node } from "react";
|
||||
import React, {
|
||||
useCallback,
|
||||
@@ -107,16 +107,19 @@ const EvidenceSectionContainer = ( {
|
||||
}, [currentObservation] );
|
||||
|
||||
const hasValidLocation = useMemo( ( ) => {
|
||||
if ( hasLocation
|
||||
&& ( latitude !== 0 && longitude !== 0 )
|
||||
&& ( latitude >= -90 && latitude <= 90 )
|
||||
&& ( longitude >= -180 && longitude <= 180 )
|
||||
&& ( currentObservation?.positional_accuracy === null
|
||||
|| currentObservation?.positional_accuracy === undefined
|
||||
|| (
|
||||
currentObservation?.positional_accuracy
|
||||
&& currentObservation?.positional_accuracy <= DESIRED_LOCATION_ACCURACY )
|
||||
)
|
||||
const coordinatesExist = latitude !== 0 && longitude !== 0;
|
||||
const latitudeInRange = latitude >= -90 && latitude <= 90;
|
||||
const longitudeInRange = longitude >= -180 && longitude <= 180;
|
||||
const positionalAccuracyBlank = isNil( currentObservation?.positional_accuracy );
|
||||
const positionalAccuracyDesireable = (
|
||||
currentObservation?.positional_accuracy || 0
|
||||
) <= DESIRED_LOCATION_ACCURACY;
|
||||
if (
|
||||
hasLocation
|
||||
&& coordinatesExist
|
||||
&& latitudeInRange
|
||||
&& longitudeInRange
|
||||
&& ( positionalAccuracyBlank || positionalAccuracyDesireable )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const SuggestionsContainer = ( ): Node => {
|
||||
longitude: currentObservation?.longitude
|
||||
} );
|
||||
|
||||
const tryOfflineSuggestions = !onlineSuggestions || onlineSuggestions?.length === 0;
|
||||
const tryOfflineSuggestions = !onlineSuggestions || onlineSuggestions?.results?.length === 0;
|
||||
const {
|
||||
offlineSuggestions,
|
||||
loadingOfflineSuggestions
|
||||
|
||||
@@ -6,7 +6,10 @@ import {
|
||||
} from "react";
|
||||
import { predictImage } from "sharedHelpers/cvModel";
|
||||
|
||||
const useOfflineSuggestions = ( selectedPhotoUri: string, options: Object ): {
|
||||
const useOfflineSuggestions = (
|
||||
selectedPhotoUri: string,
|
||||
options: Object
|
||||
): {
|
||||
offlineSuggestions: Array<Object>,
|
||||
loadingOfflineSuggestions: boolean
|
||||
} => {
|
||||
@@ -18,29 +21,24 @@ const useOfflineSuggestions = ( selectedPhotoUri: string, options: Object ): {
|
||||
useEffect( ( ) => {
|
||||
const predictOffline = async ( ) => {
|
||||
setLoadingOfflineSuggestions( true );
|
||||
try {
|
||||
const predictions = await predictImage( selectedPhotoUri );
|
||||
// using the same rank level for displaying predictions in AR Camera
|
||||
// this is all temporary, since we ultimately want predictions
|
||||
// returned similarly to how we return them on web; this is returning a
|
||||
// single branch like on the AR Camera 2023-12-08
|
||||
const formattedPredictions = predictions?.reverse( )
|
||||
.filter( prediction => prediction.rank <= 40 )
|
||||
.map( prediction => ( {
|
||||
score: prediction.score,
|
||||
taxon: {
|
||||
id: Number( prediction.taxon_id ),
|
||||
name: prediction.name,
|
||||
rank_level: prediction.rank
|
||||
}
|
||||
} ) );
|
||||
setOfflineSuggestions( formattedPredictions );
|
||||
setLoadingOfflineSuggestions( false );
|
||||
return formattedPredictions;
|
||||
} catch ( e ) {
|
||||
setLoadingOfflineSuggestions( false );
|
||||
return e;
|
||||
}
|
||||
const predictions = await predictImage( selectedPhotoUri );
|
||||
// using the same rank level for displaying predictions in AR Camera
|
||||
// this is all temporary, since we ultimately want predictions
|
||||
// returned similarly to how we return them on web; this is returning a
|
||||
// single branch like on the AR Camera 2023-12-08
|
||||
const formattedPredictions = predictions?.reverse( )
|
||||
.filter( prediction => prediction.rank <= 40 )
|
||||
.map( prediction => ( {
|
||||
score: prediction.score,
|
||||
taxon: {
|
||||
id: Number( prediction.taxon_id ),
|
||||
name: prediction.name,
|
||||
rank_level: prediction.rank
|
||||
}
|
||||
} ) );
|
||||
setOfflineSuggestions( formattedPredictions );
|
||||
setLoadingOfflineSuggestions( false );
|
||||
return formattedPredictions;
|
||||
};
|
||||
|
||||
if ( selectedPhotoUri && tryOfflineSuggestions ) {
|
||||
|
||||
@@ -27,7 +27,7 @@ const useTaxonSelected = ( selectedTaxon: ?Object, options: Object ) => {
|
||||
uuid: currentObservation.uuid,
|
||||
// TODO refactor so we're not passing complex objects as params; all
|
||||
// obs details really needs to know is the ID of the taxon
|
||||
taxonSuggested: selectedTaxon,
|
||||
suggestedTaxonId: selectedTaxon.id,
|
||||
comment,
|
||||
vision
|
||||
} );
|
||||
|
||||
@@ -111,10 +111,9 @@ class Observation extends Realm.Object {
|
||||
const taxon = obs.taxon
|
||||
? Taxon.mapApiToRealm( obs.taxon )
|
||||
: null;
|
||||
const observationPhotos = obs.observation_photos
|
||||
? obs.observation_photos.map( obsPhoto => ObservationPhoto
|
||||
.mapApiToRealm( obsPhoto, existingObs ) )
|
||||
: [];
|
||||
const observationPhotos = (
|
||||
obs.observation_photos || obs.observationPhotos || []
|
||||
).map( obsPhoto => ObservationPhoto.mapApiToRealm( obsPhoto, existingObs ) );
|
||||
|
||||
const identifications = obs.identifications
|
||||
? obs.identifications.map( id => Identification.mapApiToRealm( id ) )
|
||||
@@ -234,7 +233,7 @@ class Observation extends Realm.Object {
|
||||
const unsyncedFilter = "_synced_at == null || _synced_at <= _updated_at";
|
||||
const photosUnsyncedFilter = "ANY observationPhotos._synced_at == null";
|
||||
|
||||
const obs = realm?.objects( "Observation" );
|
||||
const obs = realm.objects( "Observation" );
|
||||
const unsyncedObs = obs.filtered( `${unsyncedFilter} || ${photosUnsyncedFilter}` );
|
||||
return unsyncedObs;
|
||||
};
|
||||
|
||||
39
tests/factories/ModelPrediction.js
Normal file
39
tests/factories/ModelPrediction.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { define } from "factoria";
|
||||
|
||||
export default define( "ModelPrediction", faker => ( {
|
||||
name: faker.person.fullName( ),
|
||||
rank: faker.helpers.arrayElement( [
|
||||
100,
|
||||
70,
|
||||
60,
|
||||
57,
|
||||
53,
|
||||
50,
|
||||
47,
|
||||
45,
|
||||
44,
|
||||
43,
|
||||
40,
|
||||
37,
|
||||
35,
|
||||
34.5,
|
||||
34,
|
||||
33.5,
|
||||
33,
|
||||
32,
|
||||
30,
|
||||
27,
|
||||
26,
|
||||
25,
|
||||
24,
|
||||
20,
|
||||
15,
|
||||
13,
|
||||
12,
|
||||
11,
|
||||
10,
|
||||
5
|
||||
] ),
|
||||
score: faker.number.float( { min: 0.8, max: 1 } ),
|
||||
taxon_id: faker.number.int( )
|
||||
} ) );
|
||||
@@ -1,5 +1,11 @@
|
||||
import { define } from "factoria";
|
||||
|
||||
import taxonFactory from "./RemoteTaxon";
|
||||
import userFactory from "./RemoteUser";
|
||||
|
||||
export default define( "RemoteIdentification", faker => ( {
|
||||
uuid: faker.string.uuid( )
|
||||
uuid: faker.string.uuid( ),
|
||||
current: true,
|
||||
user: userFactory( "RemoteUser" ),
|
||||
taxon: taxonFactory( "RemoteTaxon" )
|
||||
} ) );
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import { define } from "factoria";
|
||||
|
||||
export default define( "RemoteObservation", faker => ( {
|
||||
uuid: faker.string.uuid( )
|
||||
uuid: faker.string.uuid( ),
|
||||
geojson: {
|
||||
coordinates: [
|
||||
Number( faker.location.longitude( ) ),
|
||||
Number( faker.location.latitude( ) )
|
||||
]
|
||||
},
|
||||
positional_accuracy: 10,
|
||||
observed_on_string: "2020-04-03"
|
||||
} ) );
|
||||
|
||||
@@ -4,9 +4,8 @@ import {
|
||||
QueryClient,
|
||||
QueryClientProvider
|
||||
} from "@tanstack/react-query";
|
||||
import { render } from "@testing-library/react-native";
|
||||
import { render, screen } from "@testing-library/react-native";
|
||||
import App from "components/App";
|
||||
import ObservationsStackNavigator from "navigation/StackNavigators/ObservationsStackNavigator";
|
||||
import INatPaperProvider from "providers/INatPaperProvider";
|
||||
import React from "react";
|
||||
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
||||
@@ -49,7 +48,7 @@ function renderApp( update = null ) {
|
||||
return renderAppWithComponent( null, update );
|
||||
}
|
||||
|
||||
async function renderObservationsStackNavigatorWithObservations(
|
||||
async function renderAppWithObservations(
|
||||
observations: Array,
|
||||
realmIdentifier: string
|
||||
): any {
|
||||
@@ -72,14 +71,20 @@ async function renderObservationsStackNavigatorWithObservations(
|
||||
} );
|
||||
} ) );
|
||||
}
|
||||
renderComponent(
|
||||
<ObservationsStackNavigator />
|
||||
);
|
||||
// Render the whole app with all the navigators
|
||||
renderAppWithComponent( );
|
||||
// If we don't wait for the obs to render we get errors about things
|
||||
// happening outside of act(). Most tests will do this anyway, but this
|
||||
// caused me a lot of confusion when I was trying to debug other problems
|
||||
// by removing code until I was just rendering the stack navigator... and
|
||||
// that was still erroring out. Hopefully this will prevent that particular
|
||||
// point of confusion in the future. ~~~kueda 20240104
|
||||
await screen.findByTestId( `MyObservations.obsListItem.${observations[0].uuid}` );
|
||||
}
|
||||
|
||||
export {
|
||||
renderApp,
|
||||
renderAppWithComponent,
|
||||
renderComponent,
|
||||
renderObservationsStackNavigatorWithObservations
|
||||
renderAppWithObservations,
|
||||
renderComponent
|
||||
};
|
||||
|
||||
@@ -5,6 +5,9 @@ import nock from "nock";
|
||||
import RNSInfo from "react-native-sensitive-info";
|
||||
import { makeResponse } from "tests/factory";
|
||||
|
||||
const TEST_JWT = "test-json-web-token";
|
||||
const TEST_ACCESS_TOKEN = "test-access-token";
|
||||
|
||||
async function signOut( options = {} ) {
|
||||
const realm = options.realm || global.realm;
|
||||
i18next.language = undefined;
|
||||
@@ -21,23 +24,22 @@ async function signOut( options = {} ) {
|
||||
async function signIn( user, options = {} ) {
|
||||
const realm = options.realm || global.realm;
|
||||
await RNSInfo.setItem( "username", user.login );
|
||||
await RNSInfo.setItem( "jwtToken", "yaddayadda" );
|
||||
await RNSInfo.setItem( "jwtToken", TEST_JWT );
|
||||
await RNSInfo.setItem( "jwtGeneratedAt", Date.now( ).toString( ), {} );
|
||||
await RNSInfo.setItem( "accessToken", "yaddayadda" );
|
||||
await RNSInfo.setItem( "accessToken", TEST_ACCESS_TOKEN );
|
||||
inatjs.users.me.mockResolvedValue( makeResponse( [user] ) );
|
||||
user.signedIn = true;
|
||||
realm.write( ( ) => {
|
||||
realm.create( "User", user, "modified" );
|
||||
} );
|
||||
const accessToken = "some-token";
|
||||
nock( API_HOST )
|
||||
.post( "/oauth/token" )
|
||||
.reply( 200, { access_token: accessToken } )
|
||||
.reply( 200, { access_token: TEST_ACCESS_TOKEN } )
|
||||
.get( "/users/edit.json" )
|
||||
.reply( 200, { login: user.login, id: user.id } );
|
||||
nock( API_HOST, {
|
||||
reqheaders: {
|
||||
authorization: `Bearer ${accessToken}`
|
||||
authorization: `Bearer ${TEST_ACCESS_TOKEN}`
|
||||
}
|
||||
} )
|
||||
.get( "/users/api_token.json" )
|
||||
@@ -46,5 +48,7 @@ async function signIn( user, options = {} ) {
|
||||
|
||||
export {
|
||||
signIn,
|
||||
signOut
|
||||
signOut,
|
||||
TEST_ACCESS_TOKEN,
|
||||
TEST_JWT
|
||||
};
|
||||
|
||||
@@ -1,43 +1,28 @@
|
||||
import { faker } from "@faker-js/faker";
|
||||
import {
|
||||
// act,
|
||||
act,
|
||||
screen,
|
||||
userEvent
|
||||
userEvent,
|
||||
within
|
||||
} from "@testing-library/react-native";
|
||||
import initI18next from "i18n/initI18next";
|
||||
import inatjs from "inaturalistjs";
|
||||
import ObservationsStackNavigator from "navigation/StackNavigators/ObservationsStackNavigator";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import React from "react";
|
||||
import Realm from "realm";
|
||||
import Identification from "realmModels/Identification";
|
||||
// eslint-disable-next-line import/extensions
|
||||
import realmConfig from "realmModels/index";
|
||||
import useStore from "stores/useStore";
|
||||
import factory, { makeResponse } from "tests/factory";
|
||||
import { renderComponent } from "tests/helpers/render";
|
||||
import { renderAppWithObservations } from "tests/helpers/render";
|
||||
import { signIn, signOut, TEST_JWT } from "tests/helpers/user";
|
||||
import { getPredictionsForImage } from "vision-camera-plugin-inatvision";
|
||||
|
||||
const mockOfflinePrediction = {
|
||||
score: 0.97363,
|
||||
taxon: {
|
||||
rank_level: 10,
|
||||
name: "Felis Catus",
|
||||
id: 118552
|
||||
}
|
||||
};
|
||||
|
||||
// const mockSearchResultTaxon = factory( "RemoteTaxon" );
|
||||
|
||||
// TODO remove this mock. This is an integration test, so we should only mock
|
||||
// things outside of this app's code, which in this case is
|
||||
// vision-camera-plugin-inatvision
|
||||
jest.mock( "components/Suggestions/hooks/useOfflineSuggestions", ( ) => ( {
|
||||
__esModule: true,
|
||||
default: ( ) => ( {
|
||||
offlineSuggestions: [mockOfflinePrediction],
|
||||
loadingOfflineSuggestions: false
|
||||
} )
|
||||
} ) );
|
||||
const mockModelPrediction = factory( "ModelPrediction", {
|
||||
// useOfflineSuggestions will filter out taxa w/ rank_level > 40
|
||||
rank: 20
|
||||
} );
|
||||
|
||||
// We're explicitly testing navigation here so we want react-navigation
|
||||
// working normally
|
||||
@@ -78,10 +63,13 @@ jest.mock( "providers/contexts", ( ) => {
|
||||
};
|
||||
} );
|
||||
|
||||
const initialStoreState = useStore.getState( );
|
||||
|
||||
// Open a realm connection and stuff it in global
|
||||
beforeAll( async ( ) => {
|
||||
global.mockRealms = global.mockRealms || {};
|
||||
global.mockRealms[__filename] = await Realm.open( mockRealmConfig );
|
||||
useStore.setState( initialStoreState, true );
|
||||
await initI18next();
|
||||
// userEvent recommends fake timers
|
||||
jest.useFakeTimers( );
|
||||
@@ -94,185 +82,186 @@ afterAll( ( ) => {
|
||||
} );
|
||||
// /REALM SETUP
|
||||
|
||||
const mockUser = factory( "LocalUser", {
|
||||
login: "fake_login",
|
||||
signedIn: true
|
||||
} );
|
||||
const mockUser = factory( "LocalUser" );
|
||||
|
||||
const makeMockObservations = ( ) => ( [
|
||||
factory( "LocalObservation", {
|
||||
factory( "RemoteObservation", {
|
||||
_synced_at: faker.date.past( ),
|
||||
needsSync: jest.fn( ( ) => false ),
|
||||
wasSynced: jest.fn( ( ) => true ),
|
||||
// Suggestions won't load without a photo
|
||||
observationPhotos: [
|
||||
factory( "LocalObservationPhoto" )
|
||||
factory( "RemoteObservationPhoto" )
|
||||
],
|
||||
user: mockUser,
|
||||
positional_accuracy: 90,
|
||||
observed_on_string: "2020-01-01",
|
||||
latitude: Number( faker.location.latitude( ) ),
|
||||
longitude: Number( faker.location.longitude( ) )
|
||||
observed_on_string: "2020-01-01"
|
||||
} )
|
||||
] );
|
||||
|
||||
async function renderObservationsStackNavigatorWithObservations( observations ) {
|
||||
// Save the mock observation in Realm
|
||||
global.mockRealms[__filename].write( ( ) => {
|
||||
global.mockRealms[__filename].create( "Observation", observations[0], "modified" );
|
||||
} );
|
||||
renderComponent(
|
||||
<ObservationsStackNavigator />
|
||||
);
|
||||
async function setupAppWithSignedInUser( ) {
|
||||
const observations = makeMockObservations( );
|
||||
useStore.setState( { observations } );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
return { observations };
|
||||
}
|
||||
|
||||
// TODO restore these tests. I broke them but couldn't figure out how to fix
|
||||
// them in the time I had ~~~~kueda 20231215
|
||||
// const mockIdentification = factory( "RemoteIdentification", {
|
||||
// uuid: "123456789",
|
||||
// user: factory( "LocalUser" ),
|
||||
// taxon: factory( "LocalTaxon", {
|
||||
// name: "Miner's Lettuce",
|
||||
// rank_level: 10
|
||||
// } )
|
||||
// } );
|
||||
//
|
||||
// describe( "TaxonSearch", ( ) => {
|
||||
// beforeEach( ( ) => {
|
||||
// inatjs.identifications.create.mockResolvedValue( { results: [mockIdentification] } );
|
||||
// inatjs.search.mockResolvedValue( makeResponse( [
|
||||
// {
|
||||
// taxon: mockSearchResultTaxon
|
||||
// }
|
||||
// ] ) );
|
||||
// inatjs.observations.observers.mockResolvedValue( makeResponse( [
|
||||
// {
|
||||
// observation_count: faker.number.int( ),
|
||||
// species_count: faker.number.int( ),
|
||||
// user: factory( "RemoteUser" )
|
||||
// }
|
||||
// ] ) );
|
||||
// } );
|
||||
// Mock the response from inatjs.computervision.score_image
|
||||
const topSuggestion = {
|
||||
taxon: factory.states( "genus" )( "RemoteTaxon", { name: "Primum" } ),
|
||||
combined_score: 90
|
||||
};
|
||||
const otherSuggestion = {
|
||||
taxon: factory( "RemoteTaxon", { name: "Alia suggestione" } ),
|
||||
combined_score: 50
|
||||
};
|
||||
|
||||
// afterEach( ( ) => {
|
||||
// inatjs.identifications.create.mockReset( );
|
||||
// inatjs.search.mockReset( );
|
||||
// inatjs.observations.observers.mockReset( );
|
||||
// } );
|
||||
beforeEach( async ( ) => {
|
||||
const mockScoreImageResponse = makeResponse( [topSuggestion, otherSuggestion] );
|
||||
inatjs.computervision.score_image.mockResolvedValue( mockScoreImageResponse );
|
||||
inatjs.observations.observers.mockResolvedValue( makeResponse( ) );
|
||||
inatjs.taxa.fetch.mockResolvedValue( makeResponse( [topSuggestion.taxon] ) );
|
||||
inatjs.observations.viewedUpdates.mockResolvedValue( makeResponse( ) );
|
||||
inatjs.identifications.create.mockResolvedValue( {
|
||||
results: [factory( "RemoteIdentification", {
|
||||
taxon: topSuggestion.taxon,
|
||||
user: mockUser
|
||||
} )]
|
||||
} );
|
||||
await signIn( mockUser, { realm: global.mockRealms[__filename] } );
|
||||
} );
|
||||
|
||||
// const actor = userEvent.setup( );
|
||||
afterEach( ( ) => {
|
||||
inatjs.computervision.score_image.mockReset( );
|
||||
inatjs.observations.observers.mockReset( );
|
||||
inatjs.taxa.fetch.mockReset( );
|
||||
inatjs.observations.viewedUpdates.mockReset( );
|
||||
inatjs.identifications.create.mockReset( );
|
||||
signOut( { realm: global.mockRealms[__filename] } );
|
||||
} );
|
||||
|
||||
// // We need to navigate from MyObs to ObsDetails to Suggestions to TaxonSearch for all of these
|
||||
// // tests
|
||||
// async function navigateToTaxonSearchForObservation( observation ) {
|
||||
// const observationRow = await screen.findByTestId(
|
||||
// `MyObservations.obsListItem.${observation.uuid}`
|
||||
// );
|
||||
// await actor.press( observationRow );
|
||||
// const suggestIdButton = await screen.findByText( "SUGGEST ID" );
|
||||
// await actor.press( suggestIdButton );
|
||||
// const searchButton = await screen.findByText( "SEARCH FOR A TAXON" );
|
||||
// await actor.press( searchButton );
|
||||
// }
|
||||
describe( "TaxonSearch", ( ) => {
|
||||
const mockSearchResultTaxon = factory( "RemoteTaxon" );
|
||||
|
||||
// async function navigateToTaxonSearchForObservationViaObsEdit( observation ) {
|
||||
// const observationRow = await screen.findByTestId(
|
||||
// `MyObservations.obsListItem.${observation.uuid}`
|
||||
// );
|
||||
// await actor.press( observationRow );
|
||||
// const suggestIdButton = await screen.findByLabelText( "Edit" );
|
||||
// await actor.press( suggestIdButton );
|
||||
// const addIdButton = await screen.findByText( "ADD AN ID" );
|
||||
// await actor.press( addIdButton );
|
||||
// const searchButton = await screen.findByText( "SEARCH FOR A TAXON" );
|
||||
// await actor.press( searchButton );
|
||||
// }
|
||||
//
|
||||
// it(
|
||||
// "should create an id with false vision attribute when reached from ObsDetails via"
|
||||
// + " Suggestions and search result chosen",
|
||||
// async ( ) => {
|
||||
// const observations = makeMockObservations( );
|
||||
// await renderObservationsStackNavigatorWithObservations( observations );
|
||||
// await navigateToTaxonSearchForObservation( observations[0] );
|
||||
// const searchInput = await screen.findByLabelText( "Search for a taxon" );
|
||||
// await act(
|
||||
// async ( ) => actor.type(
|
||||
// searchInput,
|
||||
// "doesn't really matter since we're mocking the response"
|
||||
// )
|
||||
// );
|
||||
// const taxonResultButton = await screen.findByTestId(
|
||||
// `Search.taxa.${mockSearchResultTaxon.id}.checkmark`
|
||||
// );
|
||||
// expect( taxonResultButton ).toBeTruthy( );
|
||||
// await actor.press( taxonResultButton );
|
||||
// expect( await screen.findByText( "ACTIVITY" ) ).toBeTruthy( );
|
||||
// expect( inatjs.identifications.create ).toHaveBeenCalledWith( {
|
||||
// fields: Identification.ID_FIELDS,
|
||||
// identification: {
|
||||
// observation_id: observations[0].uuid,
|
||||
// taxon_id: mockSearchResultTaxon.id,
|
||||
// vision: false
|
||||
// }
|
||||
// }, {
|
||||
// api_token: null
|
||||
// } );
|
||||
// }
|
||||
// );
|
||||
|
||||
// it(
|
||||
// "should update observation with false vision attribute when reached from ObsEdit"
|
||||
// + " and search result chosen",
|
||||
// async ( ) => {
|
||||
// const observations = makeMockObservations( );
|
||||
// await renderObservationsStackNavigatorWithObservations( observations );
|
||||
// await navigateToTaxonSearchForObservationViaObsEdit( observations[0] );
|
||||
// const searchInput = await screen.findByLabelText( "Search for a taxon" );
|
||||
// await act(
|
||||
// async ( ) => actor.type(
|
||||
// searchInput,
|
||||
// "doesn't really matter since we're mocking the response"
|
||||
// )
|
||||
// );
|
||||
// const taxonResultButton = await screen.findByTestId(
|
||||
// `Search.taxa.${mockSearchResultTaxon.id}.checkmark`
|
||||
// );
|
||||
// expect( taxonResultButton ).toBeTruthy( );
|
||||
// await actor.press( taxonResultButton );
|
||||
// const saveChangesButton = await screen.findByText( "SAVE CHANGES" );
|
||||
// expect( saveChangesButton ).toBeTruthy( );
|
||||
// await actor.press( saveChangesButton );
|
||||
// const savedObservation = global.mockRealms[__filename]
|
||||
// .objectForPrimaryKey( "Observation", observations[0].uuid );
|
||||
// expect( savedObservation ).toHaveProperty( "owners_identification_from_vision", false );
|
||||
// }
|
||||
// );
|
||||
// } );
|
||||
|
||||
describe( "Suggestions", ( ) => {
|
||||
// Mock the response from inatjs.computervision.score_image
|
||||
const topSuggestion = {
|
||||
taxon: factory( "RemoteTaxon", { name: "Primum suggestion" } ),
|
||||
combined_score: 90
|
||||
};
|
||||
const otherSuggestion = {
|
||||
taxon: factory( "RemoteTaxon", { name: "Alia suggestione" } ),
|
||||
combined_score: 50
|
||||
};
|
||||
beforeEach( ( ) => {
|
||||
const mockScoreImageResponse = makeResponse( [topSuggestion, otherSuggestion] );
|
||||
inatjs.computervision.score_image.mockResolvedValue( mockScoreImageResponse );
|
||||
inatjs.observations.observers.mockResolvedValue( makeResponse( ) );
|
||||
inatjs.taxa.fetch.mockResolvedValue( makeResponse( [topSuggestion.taxon] ) );
|
||||
inatjs.search.mockResolvedValue( makeResponse( [
|
||||
{
|
||||
taxon: mockSearchResultTaxon
|
||||
}
|
||||
] ) );
|
||||
inatjs.observations.observers.mockResolvedValue( makeResponse( [
|
||||
{
|
||||
observation_count: faker.number.int( ),
|
||||
species_count: faker.number.int( ),
|
||||
user: factory( "RemoteUser" )
|
||||
}
|
||||
] ) );
|
||||
inatjs.taxa.fetch.mockResolvedValue( makeResponse( [] ) );
|
||||
} );
|
||||
|
||||
afterEach( ( ) => {
|
||||
inatjs.computervision.score_image.mockReset( );
|
||||
inatjs.search.mockReset( );
|
||||
inatjs.observations.observers.mockReset( );
|
||||
inatjs.taxa.fetch.mockReset( );
|
||||
} );
|
||||
|
||||
const actor = userEvent.setup( );
|
||||
|
||||
// We need to navigate from MyObs to ObsDetails to Suggestions to TaxonSearch for all of these
|
||||
// tests
|
||||
async function navigateToTaxonSearchForObservation( observation ) {
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observation.uuid}`
|
||||
);
|
||||
await actor.press( observationRow );
|
||||
const suggestIdButton = await screen.findByText( "SUGGEST ID" );
|
||||
await act( async ( ) => actor.press( suggestIdButton ) );
|
||||
await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${topSuggestion.taxon.id}.checkmark`
|
||||
);
|
||||
const searchButton = await screen.findByText( "SEARCH FOR A TAXON" );
|
||||
await actor.press( searchButton );
|
||||
}
|
||||
|
||||
async function navigateToTaxonSearchForObservationViaObsEdit( observation ) {
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observation.uuid}`
|
||||
);
|
||||
await actor.press( observationRow );
|
||||
const editButton = await screen.findByLabelText( "Edit" );
|
||||
await act( async ( ) => actor.press( editButton ) );
|
||||
const addIdButton = await screen.findByText( "ADD AN ID" );
|
||||
await actor.press( addIdButton );
|
||||
await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${topSuggestion.taxon.id}.checkmark`
|
||||
);
|
||||
const searchButton = await screen.findByText( "SEARCH FOR A TAXON" );
|
||||
await actor.press( searchButton );
|
||||
}
|
||||
|
||||
it(
|
||||
"should create an id with false vision attribute when reached from ObsDetails via"
|
||||
+ " Suggestions and search result chosen",
|
||||
async ( ) => {
|
||||
const { observations } = await setupAppWithSignedInUser( );
|
||||
await navigateToTaxonSearchForObservation( observations[0] );
|
||||
const searchInput = await screen.findByLabelText( "Search for a taxon" );
|
||||
expect( searchInput ).toBeVisible( );
|
||||
await act(
|
||||
async ( ) => actor.type(
|
||||
searchInput,
|
||||
"doesn't really matter since we're mocking the response"
|
||||
)
|
||||
);
|
||||
const taxonResultButton = await screen.findByTestId(
|
||||
`Search.taxa.${mockSearchResultTaxon.id}.checkmark`
|
||||
);
|
||||
expect( taxonResultButton ).toBeTruthy( );
|
||||
await actor.press( taxonResultButton );
|
||||
expect( await screen.findByText( "ACTIVITY" ) ).toBeTruthy( );
|
||||
expect( inatjs.identifications.create ).toHaveBeenCalledWith( {
|
||||
fields: Identification.ID_FIELDS,
|
||||
identification: {
|
||||
observation_id: observations[0].uuid,
|
||||
taxon_id: mockSearchResultTaxon.id,
|
||||
vision: false
|
||||
}
|
||||
}, {
|
||||
api_token: TEST_JWT
|
||||
} );
|
||||
}
|
||||
);
|
||||
|
||||
it(
|
||||
"should update observation with false vision attribute when reached from ObsEdit"
|
||||
+ " and search result chosen",
|
||||
async ( ) => {
|
||||
const { observations } = await setupAppWithSignedInUser( );
|
||||
await navigateToTaxonSearchForObservationViaObsEdit( observations[0] );
|
||||
const searchInput = await screen.findByLabelText( "Search for a taxon" );
|
||||
await act(
|
||||
async ( ) => actor.type(
|
||||
searchInput,
|
||||
"doesn't really matter since we're mocking the response"
|
||||
)
|
||||
);
|
||||
const taxonResultButton = await screen.findByTestId(
|
||||
`Search.taxa.${mockSearchResultTaxon.id}.checkmark`
|
||||
);
|
||||
expect( taxonResultButton ).toBeTruthy( );
|
||||
await actor.press( taxonResultButton );
|
||||
const saveChangesButton = await screen.findByText( "SAVE CHANGES" );
|
||||
expect( saveChangesButton ).toBeTruthy( );
|
||||
await actor.press( saveChangesButton );
|
||||
const savedObservation = global.mockRealms[__filename]
|
||||
.objectForPrimaryKey( "Observation", observations[0].uuid );
|
||||
expect( savedObservation ).toHaveProperty( "owners_identification_from_vision", false );
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
describe( "Suggestions", ( ) => {
|
||||
const actor = userEvent.setup( );
|
||||
|
||||
// We need to navigate from MyObs to ObsDetails to Suggestions for all of these
|
||||
// tests
|
||||
async function navigateToSuggestionsForObservation( observation ) {
|
||||
@@ -281,7 +270,7 @@ describe( "Suggestions", ( ) => {
|
||||
);
|
||||
await actor.press( observationRow );
|
||||
const suggestIdButton = await screen.findByText( "SUGGEST ID" );
|
||||
await actor.press( suggestIdButton );
|
||||
await act( async ( ) => actor.press( suggestIdButton ) );
|
||||
}
|
||||
|
||||
async function navigateToSuggestionsForObservationViaObsEdit( observation ) {
|
||||
@@ -289,75 +278,75 @@ describe( "Suggestions", ( ) => {
|
||||
`MyObservations.obsListItem.${observation.uuid}`
|
||||
);
|
||||
await actor.press( observationRow );
|
||||
const suggestIdButton = await screen.findByLabelText( "Edit" );
|
||||
await actor.press( suggestIdButton );
|
||||
const editButton = await screen.findByLabelText( "Edit" );
|
||||
await act( async ( ) => actor.press( editButton ) );
|
||||
const addIdButton = await screen.findByText( "ADD AN ID" );
|
||||
await actor.press( addIdButton );
|
||||
}
|
||||
|
||||
it(
|
||||
"should create an id with true vision attribute when reached from ObsDetails"
|
||||
+ " and taxon chosen",
|
||||
async ( ) => {
|
||||
const observations = makeMockObservations( );
|
||||
await renderObservationsStackNavigatorWithObservations( observations );
|
||||
await navigateToSuggestionsForObservation( observations[0] );
|
||||
const taxonId = topSuggestion.taxon.id;
|
||||
console.log( taxonId, "top computer vision suggestion" );
|
||||
const topTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${taxonId}.checkmark`
|
||||
);
|
||||
expect( topTaxonResultButton ).toBeTruthy( );
|
||||
await actor.press( topTaxonResultButton );
|
||||
expect( await screen.findByText( "ACTIVITY" ) ).toBeTruthy( );
|
||||
expect( inatjs.identifications.create ).toHaveBeenCalledWith( {
|
||||
fields: Identification.ID_FIELDS,
|
||||
identification: {
|
||||
observation_id: observations[0].uuid,
|
||||
taxon_id: taxonId,
|
||||
vision: true
|
||||
}
|
||||
}, {
|
||||
api_token: null
|
||||
} );
|
||||
}
|
||||
);
|
||||
it( "should create ident with vision=true via ObsDetails", async ( ) => {
|
||||
const { observations } = await setupAppWithSignedInUser( );
|
||||
await navigateToSuggestionsForObservation( observations[0] );
|
||||
const taxonId = topSuggestion.taxon.id;
|
||||
const topTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${taxonId}.checkmark`
|
||||
);
|
||||
expect( topTaxonResultButton ).toBeTruthy( );
|
||||
await actor.press( topTaxonResultButton );
|
||||
const activityTab = await screen.findByTestId( "ActivityTab" );
|
||||
expect( activityTab ).toBeVisible( );
|
||||
// Wait for the actual identification we created to appear
|
||||
const taxonNameInIdent = await within( activityTab ).findByText( topSuggestion.taxon.name );
|
||||
expect( taxonNameInIdent ).toBeVisible( );
|
||||
expect( inatjs.identifications.create ).toHaveBeenCalledWith( {
|
||||
fields: Identification.ID_FIELDS,
|
||||
identification: {
|
||||
observation_id: observations[0].uuid,
|
||||
taxon_id: taxonId,
|
||||
vision: true
|
||||
}
|
||||
}, {
|
||||
api_token: TEST_JWT
|
||||
} );
|
||||
} );
|
||||
|
||||
it(
|
||||
"should update observation with true vision attribute when reached from ObsEdit"
|
||||
+ " and taxon chosen",
|
||||
async ( ) => {
|
||||
const observations = makeMockObservations( );
|
||||
await renderObservationsStackNavigatorWithObservations( observations );
|
||||
await navigateToSuggestionsForObservationViaObsEdit( observations[0] );
|
||||
const topTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${topSuggestion.taxon.id}.checkmark`
|
||||
);
|
||||
expect( topTaxonResultButton ).toBeTruthy( );
|
||||
await actor.press( topTaxonResultButton );
|
||||
const saveChangesButton = await screen.findByText( "SAVE CHANGES" );
|
||||
expect( saveChangesButton ).toBeTruthy( );
|
||||
await actor.press( saveChangesButton );
|
||||
const savedObservation = global.mockRealms[__filename]
|
||||
.objectForPrimaryKey( "Observation", observations[0].uuid );
|
||||
expect( savedObservation ).toHaveProperty( "owners_identification_from_vision", true );
|
||||
}
|
||||
);
|
||||
it( "should update observation with vision=true via ObsEdit", async ( ) => {
|
||||
const { observations } = await setupAppWithSignedInUser( );
|
||||
await navigateToSuggestionsForObservationViaObsEdit( observations[0] );
|
||||
const topTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${topSuggestion.taxon.id}.checkmark`
|
||||
);
|
||||
expect( topTaxonResultButton ).toBeTruthy( );
|
||||
await actor.press( topTaxonResultButton );
|
||||
const saveChangesButton = await screen.findByText( "SAVE CHANGES" );
|
||||
expect( saveChangesButton ).toBeTruthy( );
|
||||
await actor.press( saveChangesButton );
|
||||
// Ensure we're back on MyObs
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observations[0].uuid}`
|
||||
);
|
||||
expect( observationRow ).toBeVisible( );
|
||||
const savedObservation = global.mockRealms[__filename]
|
||||
.objectForPrimaryKey( "Observation", observations[0].uuid );
|
||||
expect( savedObservation ).toHaveProperty( "owners_identification_from_vision", true );
|
||||
} );
|
||||
|
||||
it(
|
||||
"should try offline suggestions if no online suggestions are found",
|
||||
async ( ) => {
|
||||
const mockScoreImageResponse = makeResponse( [] );
|
||||
inatjs.computervision.score_image.mockResolvedValue( mockScoreImageResponse );
|
||||
const observations = makeMockObservations( );
|
||||
await renderObservationsStackNavigatorWithObservations( observations );
|
||||
await navigateToSuggestionsForObservationViaObsEdit( observations[0] );
|
||||
|
||||
const topOnlineTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${mockOfflinePrediction.taxon.id}.checkmark`
|
||||
inatjs.computervision.score_image.mockResolvedValue( makeResponse( [] ) );
|
||||
getPredictionsForImage.mockImplementation(
|
||||
async ( ) => ( [mockModelPrediction] )
|
||||
);
|
||||
expect( topOnlineTaxonResultButton ).toBeTruthy( );
|
||||
await actor.press( topOnlineTaxonResultButton );
|
||||
const { observations } = await setupAppWithSignedInUser( );
|
||||
await navigateToSuggestionsForObservationViaObsEdit( observations[0] );
|
||||
const offlineNotice = await screen.findByText( "Viewing Offline Suggestions" );
|
||||
expect( offlineNotice ).toBeVisible( );
|
||||
const topOfflineTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${mockModelPrediction.taxon_id}.checkmark`
|
||||
);
|
||||
expect( topOfflineTaxonResultButton ).toBeTruthy( );
|
||||
await act( async ( ) => actor.press( topOfflineTaxonResultButton ) );
|
||||
const saveChangesButton = await screen.findByText( "SAVE CHANGES" );
|
||||
expect( saveChangesButton ).toBeTruthy( );
|
||||
await actor.press( saveChangesButton );
|
||||
|
||||
@@ -12,7 +12,7 @@ import useStore from "stores/useStore";
|
||||
import factory, { makeResponse } from "tests/factory";
|
||||
import {
|
||||
renderApp,
|
||||
renderObservationsStackNavigatorWithObservations
|
||||
renderAppWithObservations
|
||||
} from "tests/helpers/render";
|
||||
import { signIn, signOut } from "tests/helpers/user";
|
||||
|
||||
@@ -121,7 +121,7 @@ describe( "MediaViewer navigation", ( ) => {
|
||||
} );
|
||||
|
||||
async function navigateToObsEdit( ) {
|
||||
await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observation.uuid}`
|
||||
);
|
||||
@@ -203,7 +203,7 @@ describe( "MediaViewer navigation", ( ) => {
|
||||
useStore.setState( { observations } );
|
||||
|
||||
async function navigateToObsDetail( ) {
|
||||
await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observation.uuid}`
|
||||
);
|
||||
@@ -276,7 +276,7 @@ describe( "MediaViewer navigation", ( ) => {
|
||||
} );
|
||||
|
||||
async function navigateToTaxonDetail( ) {
|
||||
await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observation.uuid}`
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import Realm from "realm";
|
||||
import realmConfig from "realmModels/index";
|
||||
import factory from "tests/factory";
|
||||
import {
|
||||
renderObservationsStackNavigatorWithObservations
|
||||
renderAppWithObservations
|
||||
} from "tests/helpers/render";
|
||||
import { signIn, signOut } from "tests/helpers/user";
|
||||
|
||||
@@ -96,7 +96,7 @@ describe( "ObsEdit", ( ) => {
|
||||
} );
|
||||
|
||||
async function navigateToObsEditOrObsDetails( observations ) {
|
||||
await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
const observationRow = await screen.findByTestId(
|
||||
`MyObservations.obsListItem.${observations[0].uuid}`
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
// act,
|
||||
act,
|
||||
screen,
|
||||
userEvent
|
||||
} from "@testing-library/react-native";
|
||||
@@ -12,9 +12,7 @@ import Realm from "realm";
|
||||
import realmConfig from "realmModels/index";
|
||||
import useStore from "stores/useStore";
|
||||
import factory, { makeResponse } from "tests/factory";
|
||||
import { renderObservationsStackNavigatorWithObservations } from "tests/helpers/render";
|
||||
|
||||
const initialStoreState = useStore.getState( );
|
||||
import { renderAppWithObservations } from "tests/helpers/render";
|
||||
|
||||
// We're explicitly testing navigation here so we want react-navigation
|
||||
// working normally
|
||||
@@ -56,6 +54,8 @@ jest.mock( "providers/contexts", ( ) => {
|
||||
};
|
||||
} );
|
||||
|
||||
const initialStoreState = useStore.getState( );
|
||||
|
||||
// Open a realm connection and stuff it in global
|
||||
beforeAll( async ( ) => {
|
||||
global.mockRealms = global.mockRealms || {};
|
||||
@@ -127,7 +127,7 @@ describe( "Suggestions", ( ) => {
|
||||
async ( ) => {
|
||||
const observations = makeMockObservations( );
|
||||
useStore.setState( { observations } );
|
||||
await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
await navigateToSuggestionsForObservation( observations[0] );
|
||||
const topTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${topSuggestion.taxon.id}.checkmark`
|
||||
@@ -141,7 +141,7 @@ describe( "Suggestions", ( ) => {
|
||||
|
||||
it( "should navigate back to ObsEdit when another suggestion chosen", async ( ) => {
|
||||
const observations = makeMockObservations( );
|
||||
await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
await navigateToSuggestionsForObservation( observations[0] );
|
||||
const otherTaxonResultButton = await screen.findByTestId(
|
||||
`SuggestionsList.taxa.${otherSuggestion.taxon.id}.checkmark`
|
||||
@@ -152,40 +152,40 @@ describe( "Suggestions", ( ) => {
|
||||
} );
|
||||
} );
|
||||
|
||||
// TODO restore these tests. I broke them but couldn't figure out how to fix
|
||||
// them in the time I had ~~~~kueda 20231215
|
||||
// describe( "TaxonSearch", ( ) => {
|
||||
// it(
|
||||
// "should navigate back to ObsEdit with expected observation"
|
||||
// + " when reached from ObsEdit via Suggestions and search result chosen",
|
||||
// async ( ) => {
|
||||
// const observations = makeMockObservations( );
|
||||
// useStore.setState( { observations } );
|
||||
// await renderObservationsStackNavigatorWithObservations( observations, __filename );
|
||||
// await navigateToSuggestionsForObservation( observations[0] );
|
||||
// const searchButton = await screen.findByText( "SEARCH FOR A TAXON" );
|
||||
// await actor.press( searchButton );
|
||||
// const searchInput = await screen.findByLabelText( "Search for a taxon" );
|
||||
// const mockSearchResultTaxon = factory( "RemoteTaxon" );
|
||||
// inatjs.search.mockResolvedValue( makeResponse( [
|
||||
// {
|
||||
// taxon: mockSearchResultTaxon
|
||||
// }
|
||||
// ] ) );
|
||||
// await act(
|
||||
// async ( ) => actor.type(
|
||||
// searchInput,
|
||||
// "doesn't really matter since we're mocking the response"
|
||||
// )
|
||||
// );
|
||||
// const taxonResultButton = await screen.findByTestId(
|
||||
// `Search.taxa.${mockSearchResultTaxon.id}.checkmark`
|
||||
// );
|
||||
// expect( taxonResultButton ).toBeTruthy( );
|
||||
// await actor.press( taxonResultButton );
|
||||
// expect( await screen.findByText( "EVIDENCE" ) ).toBeTruthy( );
|
||||
// expect( await screen.findByText( /Obscured/ ) ).toBeVisible( );
|
||||
// }
|
||||
// );
|
||||
// } );
|
||||
describe( "TaxonSearch", ( ) => {
|
||||
it(
|
||||
"should navigate back to ObsEdit with expected observation"
|
||||
+ " when reached from ObsEdit via Suggestions and search result chosen",
|
||||
async ( ) => {
|
||||
const observations = [
|
||||
factory( "LocalObservation", { geoprivacy: "obscured" } )
|
||||
];
|
||||
useStore.setState( { observations } );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
await navigateToSuggestionsForObservation( observations[0] );
|
||||
const searchButton = await screen.findByText( "SEARCH FOR A TAXON" );
|
||||
await actor.press( searchButton );
|
||||
const searchInput = await screen.findByLabelText( "Search for a taxon" );
|
||||
const mockSearchResultTaxon = factory( "RemoteTaxon" );
|
||||
inatjs.search.mockResolvedValue( makeResponse( [
|
||||
{
|
||||
taxon: mockSearchResultTaxon
|
||||
}
|
||||
] ) );
|
||||
await act(
|
||||
async ( ) => actor.type(
|
||||
searchInput,
|
||||
"doesn't really matter since we're mocking the response"
|
||||
)
|
||||
);
|
||||
const taxonResultButton = await screen.findByTestId(
|
||||
`Search.taxa.${mockSearchResultTaxon.id}.checkmark`
|
||||
);
|
||||
expect( taxonResultButton ).toBeTruthy( );
|
||||
await actor.press( taxonResultButton );
|
||||
expect( await screen.findByText( "EVIDENCE" ) ).toBeTruthy( );
|
||||
expect( await screen.findByText( /Obscured/ ) ).toBeVisible( );
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from "./vision-camera/vision-camera";
|
||||
|
||||
jest.mock( "vision-camera-plugin-inatvision", () => ( {
|
||||
getPredictionsForImage: jest.fn( () => Promise.resolve( "Mocked cv prediction" ) )
|
||||
getPredictionsForImage: jest.fn( () => Promise.resolve( [] ) )
|
||||
} ) );
|
||||
|
||||
jest.mock( "react-native-worklets-core", () => ( {
|
||||
|
||||
Reference in New Issue
Block a user