diff --git a/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts b/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts index 29b2ccdfa..703d30627 100644 --- a/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts +++ b/src/components/Camera/hooks/usePrepareStoreAndNavigate.ts @@ -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", diff --git a/src/components/Match/MatchContainer.js b/src/components/Match/MatchContainer.js index 87a8af8f0..58b17772d 100644 --- a/src/components/Match/MatchContainer.js +++ b/src/components/Match/MatchContainer.js @@ -45,6 +45,8 @@ const MatchContainer = ( ) => { fetchStatus } = useStore.getState( ); + console.log( isLoading, "is loading" ); + const updateObservationKeys = useStore( state => state.updateObservationKeys ); const navigation = useNavigation( ); const { diff --git a/src/sharedHooks/index.js b/src/sharedHooks/index.js index bb1bdeb4d..7d47340cf 100644 --- a/src/sharedHooks/index.js +++ b/src/sharedHooks/index.js @@ -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 diff --git a/tests/integration/navigation/Match.test.js b/tests/integration/navigation/Match.test.js deleted file mode 100644 index 90a2b31a5..000000000 --- a/tests/integration/navigation/Match.test.js +++ /dev/null @@ -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( ); - } ); - } ); -} ); diff --git a/tests/unit/components/BottomTabNavigator/__snapshots__/CustomTabBar.test.js.snap b/tests/unit/components/BottomTabNavigator/__snapshots__/CustomTabBar.test.js.snap index b47f7aad6..e67fd3af8 100644 --- a/tests/unit/components/BottomTabNavigator/__snapshots__/CustomTabBar.test.js.snap +++ b/tests/unit/components/BottomTabNavigator/__snapshots__/CustomTabBar.test.js.snap @@ -163,7 +163,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = ` ] } > -  +  @@ -307,7 +307,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = ` ] } > -  +  @@ -513,7 +513,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = ` ] } > -  +  @@ -624,7 +624,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = ` ] } > -  +  @@ -768,7 +768,7 @@ exports[`CustomTabBar with advanced user layout should render correctly 1`] = ` ] } > -  +  diff --git a/tests/unit/components/Match/Match.test.js b/tests/unit/components/Match/Match.test.js new file mode 100644 index 000000000..99d50ba23 --- /dev/null +++ b/tests/unit/components/Match/Match.test.js @@ -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( + + ); + + 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( + + ); + + const addLocationButton = screen.queryByText( /ADD LOCATION FOR BETTER IDS/i ); + expect( addLocationButton ).toBeFalsy( ); + } ); +} ); diff --git a/tests/unit/components/SharedComponents/ActivityCount/__snapshots__/ActivityCount.test.js.snap b/tests/unit/components/SharedComponents/ActivityCount/__snapshots__/ActivityCount.test.js.snap index 089eef5e8..03279f63e 100644 --- a/tests/unit/components/SharedComponents/ActivityCount/__snapshots__/ActivityCount.test.js.snap +++ b/tests/unit/components/SharedComponents/ActivityCount/__snapshots__/ActivityCount.test.js.snap @@ -36,7 +36,7 @@ exports[`ActivityCount renders reliably 1`] = ` ] } > -  +  -  +  -  +  -  +  -  +  -  +  -  +  -  +  diff --git a/tests/unit/components/SharedComponents/InlineUser/__snapshots__/InlineUser.test.js.snap b/tests/unit/components/SharedComponents/InlineUser/__snapshots__/InlineUser.test.js.snap index 7879727b4..cefc9c831 100644 --- a/tests/unit/components/SharedComponents/InlineUser/__snapshots__/InlineUser.test.js.snap +++ b/tests/unit/components/SharedComponents/InlineUser/__snapshots__/InlineUser.test.js.snap @@ -194,7 +194,7 @@ exports[`InlineUser when offline renders reliably 1`] = ` } testID="InlineUser.FallbackPicture" > -  +  -  +  -  +  @@ -359,7 +359,7 @@ exports[`ObsGridItem for an observation without a photo should render 1`] = ` ] } > -  +  diff --git a/tests/unit/components/SharedComponents/UploadStatus/__snapshots__/UploadStatus.test.js.snap b/tests/unit/components/SharedComponents/UploadStatus/__snapshots__/UploadStatus.test.js.snap index 25eeae4ac..ca8fe9bcf 100644 --- a/tests/unit/components/SharedComponents/UploadStatus/__snapshots__/UploadStatus.test.js.snap +++ b/tests/unit/components/SharedComponents/UploadStatus/__snapshots__/UploadStatus.test.js.snap @@ -114,7 +114,7 @@ exports[`UploadStatus displays complete icon when progress is 1 1`] = ` ] } > -  +  @@ -238,7 +238,7 @@ exports[`UploadStatus displays progress bar when progress is greater than 5% 1`] ] } > -  +  -  +  -  +  @@ -524,7 +524,7 @@ exports[`UploadStatus displays start icon when upload is unsynced and not queued ] } > -  +  -  +  diff --git a/tests/unit/components/SharedComponents/__snapshots__/Checkbox.test.js.snap b/tests/unit/components/SharedComponents/__snapshots__/Checkbox.test.js.snap index 3de06b0ff..58f544382 100644 --- a/tests/unit/components/SharedComponents/__snapshots__/Checkbox.test.js.snap +++ b/tests/unit/components/SharedComponents/__snapshots__/Checkbox.test.js.snap @@ -278,7 +278,7 @@ exports[`Checkbox renders reliably being checked 1`] = ` ] } > -  +  diff --git a/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap b/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap index 633f59fb5..b4e5303e6 100644 --- a/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap +++ b/tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap @@ -255,7 +255,7 @@ exports[`TaxonResult should render correctly 1`] = ` ] } > -  +  @@ -511,7 +511,7 @@ exports[`TaxonResult should render correctly 1`] = ` ] } > -  +  @@ -606,7 +606,7 @@ exports[`TaxonResult should render correctly 1`] = ` ] } > -  +  diff --git a/tests/unit/components/__snapshots__/INatIcon.test.js.snap b/tests/unit/components/__snapshots__/INatIcon.test.js.snap index 0e81b16a9..7ad7012a7 100644 --- a/tests/unit/components/__snapshots__/INatIcon.test.js.snap +++ b/tests/unit/components/__snapshots__/INatIcon.test.js.snap @@ -20,6 +20,6 @@ exports[`INatIcon renders correctly 1`] = ` ] } > -  +  `;