mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2025-12-23 22:18:36 -05:00
Update tests
This commit is contained in:
@@ -163,6 +163,8 @@ const usePrepareStoreAndNavigate = ( ): Function => {
|
||||
await deleteStageIfAICamera( );
|
||||
setSentinelFileName( null );
|
||||
|
||||
console.log( "navigating from AI camera usePrepareSTore" );
|
||||
|
||||
if ( showMatchScreen ) {
|
||||
return navigation.push( "Match", {
|
||||
entryScreen: "CameraWithDevice",
|
||||
|
||||
@@ -45,6 +45,8 @@ const MatchContainer = ( ) => {
|
||||
fetchStatus
|
||||
} = useStore.getState( );
|
||||
|
||||
console.log( isLoading, "is loading" );
|
||||
|
||||
const updateObservationKeys = useStore( state => state.updateObservationKeys );
|
||||
const navigation = useNavigation( );
|
||||
const {
|
||||
|
||||
@@ -31,6 +31,9 @@ export { default as useStoredLayout } from "./useStoredLayout";
|
||||
export {
|
||||
default as useOfflineSuggestionsForMatch
|
||||
} from "./useSuggestions/useOfflineSuggestionsForMatch";
|
||||
export {
|
||||
default as useOnlineSuggestionsForMatch
|
||||
} from "./useSuggestions/useOnlineSuggestionsForMatch";
|
||||
export { default as useSuggestions } from "./useSuggestions/useSuggestions";
|
||||
export {
|
||||
default as useSuggestionsForMatch
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
import Geolocation from "@react-native-community/geolocation";
|
||||
import {
|
||||
screen,
|
||||
userEvent,
|
||||
waitFor,
|
||||
within
|
||||
} from "@testing-library/react-native";
|
||||
import * as usePredictions from "components/Camera/AICamera/hooks/usePredictions.ts";
|
||||
import initI18next from "i18n/initI18next";
|
||||
import inatjs from "inaturalistjs";
|
||||
import * as useLocationPermission from "sharedHooks/useLocationPermission.tsx";
|
||||
import useStore from "stores/useStore";
|
||||
import factory, { makeResponse } from "tests/factory";
|
||||
import { renderAppWithObservations } from "tests/helpers/render";
|
||||
import setupUniqueRealm from "tests/helpers/uniqueRealm";
|
||||
|
||||
jest.mock( "react-native/Libraries/Utilities/Platform", ( ) => ( {
|
||||
OS: "ios",
|
||||
select: jest.fn( ),
|
||||
Version: 11
|
||||
} ) );
|
||||
|
||||
// We're explicitly testing navigation here so we want react-navigation
|
||||
// working normally
|
||||
jest.unmock( "@react-navigation/native" );
|
||||
|
||||
// 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],
|
||||
useQuery: ( ) => []
|
||||
}
|
||||
};
|
||||
} );
|
||||
beforeAll( uniqueRealmBeforeAll );
|
||||
afterAll( uniqueRealmAfterAll );
|
||||
// /UNIQUE REALM SETUP
|
||||
|
||||
const makeUnsyncedObservations = options => ( [
|
||||
factory( "LocalObservation", {
|
||||
// Match won't load without a photo
|
||||
observationPhotos: [
|
||||
factory( "LocalObservationPhoto" )
|
||||
],
|
||||
...options
|
||||
} )
|
||||
] );
|
||||
|
||||
const topSuggestion = {
|
||||
taxon: factory( "RemoteTaxon", { name: "Primum suggestion" } ),
|
||||
combined_score: 78
|
||||
};
|
||||
|
||||
beforeEach( async ( ) => {
|
||||
useStore.setState( {
|
||||
layout: {
|
||||
isDefaultMode: true,
|
||||
shownOnce: {}
|
||||
},
|
||||
isAdvancedUser: false
|
||||
} );
|
||||
} );
|
||||
|
||||
afterEach( ( ) => {
|
||||
inatjs.computervision.score_image.mockClear( );
|
||||
} );
|
||||
|
||||
beforeAll( async () => {
|
||||
await initI18next();
|
||||
// userEvent recommends fake timers
|
||||
jest.useFakeTimers( );
|
||||
} );
|
||||
|
||||
describe( "Match", ( ) => {
|
||||
global.withAnimatedTimeTravelEnabled( { skipFakeTimers: true } );
|
||||
const actor = userEvent.setup( );
|
||||
|
||||
async function navigateToMatchViaCamera( ) {
|
||||
const tabBar = await screen.findByTestId( "CustomTabBar" );
|
||||
const addObsButton = await within( tabBar ).findByLabelText( "Add observations" );
|
||||
await actor.press( addObsButton );
|
||||
const takePhotoButton = await screen.findByLabelText( /Take photo/ );
|
||||
await actor.press( takePhotoButton );
|
||||
const discardButton = await screen.findByText( /DISCARD/ );
|
||||
await waitFor( ( ) => {
|
||||
global.timeTravel( );
|
||||
expect( discardButton ).toBeVisible( );
|
||||
} );
|
||||
}
|
||||
|
||||
describe( "when reached from Camera", ( ) => {
|
||||
beforeEach( ( ) => {
|
||||
inatjs.computervision.score_image
|
||||
.mockResolvedValue( makeResponse( [topSuggestion] ) );
|
||||
jest.spyOn( usePredictions, "default" ).mockImplementation( () => ( {
|
||||
handleTaxaDetected: jest.fn( ),
|
||||
modelLoaded: true,
|
||||
result: {
|
||||
taxon: []
|
||||
},
|
||||
setResult: jest.fn( )
|
||||
} ) );
|
||||
} );
|
||||
|
||||
it( "should show location permissions button if permissions not granted", async ( ) => {
|
||||
jest.spyOn( useLocationPermission, "default" ).mockImplementation( ( ) => ( {
|
||||
hasPermissions: false,
|
||||
renderPermissionsGate: jest.fn( )
|
||||
} ) );
|
||||
const observations = makeUnsyncedObservations( );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
await navigateToMatchViaCamera( );
|
||||
const addLocationButton = screen.queryByText( /ADD LOCATION FOR BETTER IDS/ );
|
||||
expect( addLocationButton ).toBeVisible( );
|
||||
} );
|
||||
|
||||
it( "should not show location permissions button if permissions granted", async ( ) => {
|
||||
const mockWatchPosition = jest.fn( ( success, _error, _options ) => success( {
|
||||
coords: {
|
||||
latitude: 56,
|
||||
longitude: 9,
|
||||
accuracy: 8
|
||||
}
|
||||
} ) );
|
||||
Geolocation.watchPosition.mockImplementation( mockWatchPosition );
|
||||
jest.spyOn( useLocationPermission, "default" ).mockImplementation( ( ) => ( {
|
||||
hasPermissions: true,
|
||||
renderPermissionsGate: jest.fn( )
|
||||
} ) );
|
||||
const observations = makeUnsyncedObservations( );
|
||||
await renderAppWithObservations( observations, __filename );
|
||||
await navigateToMatchViaCamera( );
|
||||
const addLocationButton = screen.queryByText( /ADD LOCATION FOR BETTER IDS/ );
|
||||
expect( addLocationButton ).toBeFalsy( );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
@@ -163,7 +163,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -307,7 +307,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -513,7 +513,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</BVLinearGradient>
|
||||
@@ -624,7 +624,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -768,7 +768,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
77
tests/unit/components/Match/Match.test.js
Normal file
77
tests/unit/components/Match/Match.test.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import Geolocation from "@react-native-community/geolocation";
|
||||
import { screen } from "@testing-library/react-native";
|
||||
import Match from "components/Match/Match";
|
||||
import initI18next from "i18n/initI18next";
|
||||
import React from "react";
|
||||
import * as useLocationPermission from "sharedHooks/useLocationPermission.tsx";
|
||||
import factory from "tests/factory";
|
||||
import { renderComponent } from "tests/helpers/render";
|
||||
|
||||
// Initialize i18next for translations
|
||||
beforeAll( async () => {
|
||||
await initI18next();
|
||||
} );
|
||||
|
||||
describe( "Match", ( ) => {
|
||||
// Mock props that would normally come from MatchContainer
|
||||
const defaultProps = {
|
||||
observation: factory( "LocalObservation" ),
|
||||
obsPhotos: [factory( "LocalObservationPhoto" )],
|
||||
onSuggestionChosen: jest.fn(),
|
||||
handleSaveOrDiscardPress: jest.fn(),
|
||||
navToTaxonDetails: jest.fn(),
|
||||
handleAddLocationPressed: jest.fn(),
|
||||
scrollRef: { current: null }
|
||||
};
|
||||
|
||||
beforeEach( () => {
|
||||
jest.clearAllMocks();
|
||||
} );
|
||||
|
||||
it( "should show location permissions button if permissions not granted", () => {
|
||||
jest.spyOn( useLocationPermission, "default" ).mockImplementation( ( ) => ( {
|
||||
hasPermissions: false,
|
||||
renderPermissionsGate: jest.fn( )
|
||||
} ) );
|
||||
renderComponent(
|
||||
<Match
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...defaultProps}
|
||||
observation={defaultProps.observation}
|
||||
/>
|
||||
);
|
||||
|
||||
const addLocationButton = screen.queryByText( /ADD LOCATION FOR BETTER IDS/i );
|
||||
expect( addLocationButton ).toBeVisible();
|
||||
} );
|
||||
|
||||
it( "should not show location permissions button if permissions granted", () => {
|
||||
const mockWatchPosition = jest.fn( ( success, _error, _options ) => success( {
|
||||
coords: {
|
||||
latitude: 56,
|
||||
longitude: 9,
|
||||
accuracy: 8
|
||||
}
|
||||
} ) );
|
||||
Geolocation.watchPosition.mockImplementation( mockWatchPosition );
|
||||
jest.spyOn( useLocationPermission, "default" ).mockImplementation( ( ) => ( {
|
||||
hasPermissions: true,
|
||||
renderPermissionsGate: jest.fn( )
|
||||
} ) );
|
||||
|
||||
renderComponent(
|
||||
<Match
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...defaultProps}
|
||||
observation={{
|
||||
...defaultProps.observation,
|
||||
latitude: 24,
|
||||
longitude: -24
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const addLocationButton = screen.queryByText( /ADD LOCATION FOR BETTER IDS/i );
|
||||
expect( addLocationButton ).toBeFalsy( );
|
||||
} );
|
||||
} );
|
||||
@@ -36,7 +36,7 @@ exports[`ActivityCount renders reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
|
||||
@@ -36,7 +36,7 @@ exports[`CommentsCount renders default reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
@@ -111,7 +111,7 @@ exports[`CommentsCount renders filled reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
@@ -186,7 +186,7 @@ exports[`CommentsCount renders white reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
|
||||
@@ -36,7 +36,7 @@ exports[`IdentificationsCount renders default reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
@@ -111,7 +111,7 @@ exports[`IdentificationsCount renders filled reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
@@ -186,7 +186,7 @@ exports[`IdentificationsCount renders white reliably 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
<Text
|
||||
maxFontSizeMultiplier={2}
|
||||
|
||||
@@ -87,7 +87,7 @@ exports[`INatIconButton renders correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -194,7 +194,7 @@ exports[`InlineUser when offline renders reliably 1`] = `
|
||||
}
|
||||
testID="InlineUser.FallbackPicture"
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
@@ -322,7 +322,7 @@ exports[`InlineUser when user has no icon set renders reliably 1`] = `
|
||||
}
|
||||
testID="InlineUser.FallbackPicture"
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
|
||||
@@ -117,7 +117,7 @@ exports[`ObsGridItem for an observation with a photo should render 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -359,7 +359,7 @@ exports[`ObsGridItem for an observation without a photo should render 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -114,7 +114,7 @@ exports[`UploadStatus displays complete icon when progress is 1 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -238,7 +238,7 @@ exports[`UploadStatus displays progress bar when progress is greater than 5% 1`]
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
<CircularProgress
|
||||
@@ -328,7 +328,7 @@ exports[`UploadStatus displays rotating circle progress when upload is queued bu
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
@@ -376,7 +376,7 @@ exports[`UploadStatus displays rotating circle progress when upload is queued bu
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -524,7 +524,7 @@ exports[`UploadStatus displays start icon when upload is unsynced and not queued
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
@@ -572,7 +572,7 @@ exports[`UploadStatus displays start icon when upload is unsynced and not queued
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -278,7 +278,7 @@ exports[`Checkbox renders reliably being checked 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -255,7 +255,7 @@ exports[`TaxonResult should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -511,7 +511,7 @@ exports[`TaxonResult should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -606,7 +606,7 @@ exports[`TaxonResult should render correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -20,6 +20,6 @@ exports[`INatIcon renders correctly 1`] = `
|
||||
]
|
||||
}
|
||||
>
|
||||
|
||||
|
||||
</Text>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user